【发布时间】:2017-10-20 19:22:00
【问题描述】:
我正在尝试使用 CGLib 创建自己的延迟加载实现,但我遇到了一些我无法解释的奇怪行为。
这就是我正在做的事情。
正在创建代理实例,如下所示:
public static <T> T newInstance(Long sourceId, SourceMapper<T> sourceMapper) {
Class<?> proxyTargetType = sourceMapper.getType();
//mapper will use provided sourceId in order to load real object from the DB
Function<Long, T> mapper = sourceMapper.getMapper();
return (T) Enhancer.create(proxyTargetType,
new DynamicProxy<>(sourceId, mapper));
}
下面是上面代码的用法:
Order order = new Order();
try {
//heavy object is being proxied
long customerTariffId = rs.getLong("customer_tariff_id");
order.setCustomerTariff(DynamicProxy
.newInstance(customerTariffId, CUSTOMER_TARIFF_MAPPER));
}
只有当它的任何方法被调用时才应该加载重对象:
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
T source = this.getSource(); // loads real object using sourceId and mapper
if(source == null) return null;
return method.invoke(source, args);
}
如果this.getSource() 加载某个对象,它会完美运行。
但是如果我们假设order.getCustomerTariff() 应该返回null(this.getSource() 将返回null),我会得到什么
LOG.debug("{}", order.getCustomerTariff()); //null (1)
LOG.debug("{}", order.getCustomerTariff() != null); //true (2)
我假设,出于某种原因,toString() 在第 (2) 行被调用,所以我得到的是 String null 而不是文字 null。这就是为什么它不等于比较子句中的文字 null。
您如何看待,有没有办法在第 (2) 行返回常规 null 并接收正确的值 false检查期间?
编辑
被代理的类看起来像这样:
public class CustomerTariff extends DomainEntity {
private Customer customer;
//some other similar fields
private Tariff tariff;
public CustomerTariff() {
}
public CustomerTariff(Customer customer
Tariff tariff) {
this.customer = customer;
this.tariff = tariff;
}
public CustomerTariff(Long id, Customer customer,
Tariff tariff) {
super(id);
this.customer = customer;
this.tariff = tariff;
}
//getters and setters
@Override
public String toString() {
return "CustomerTariff{" +
"customer=" + customer +
", tariff=" + tariff +
"} " + super.toString();
}
}
public abstract class DomainEntity {
private Long id;
public DomainEntity() {}
public DomainEntity(Long id) {
this.id = id;
}
@Override
public String toString() {
return "DomainEntity{" +
"id=" + id +
'}';
}
}
【问题讨论】:
-
你所做的似乎是正确的。您是否检查了返回值的类型?您是否在拦截器中设置了断点来检查返回的正确值?
-
@RafaelWinterhalter 从调试会话中我了解到,
Enhancer.create(...)生成以下值obj = {CustomerTariff$$EnhancerByCGLIB$$d66ba677} "null",该值被设置为customerTariff字段。此值与第 (2) 行的null进行比较。我不明白引用的 null 是什么意思,但问题是"null" != null产生true -
我假设有一些构造函数定义了一个值,该值成为
toString表示的一部分。我假设您调用了构造函数,但不初始化正在读取的某些字段。你能提供被代理的类吗? -
@RafaelWinterhalter 是的,我可以提供课程。我已经编辑了我的问题