我有一个注释
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PartnerProxy {
}
和建议
@Component
@Aspect
public class AnnotationAdvice {
@Around("@annotation(PartnerProxy)")
public Object pc(ProceedingJoinPoint joinPoint) throws Throwable {
return joinPoint.proceed();
}
}
我想代理的豆子
public class OuterServiceProxy {
private IRoomStatusService service;
... another properties
String getRemoteHourRoomStatus(){
return service.echo();
}
@PartnerProxy
public void hello() {
}
...getters & setters
有一个属性
IRoomStatusService service
,这就是重点。首先,如果我在spring xml文件中声明
OuterServiceProxy
<bean id="outerServiceProxy" class="aop.jg.OuterServiceProxy">
<property name="service" ref="service"/>
</bean>
当调用
outerServiceProxy.getRemoteHourRoomStatus()
方法时,将引发NPE。我调试到那条线[1]String getRemoteHourRoomStatus(){
return service.echo(); [1]
}
service
为空。但是outerServiceProxy
实际上是Cglib增强的OuterServiceProxy$$EnhancerByCGLIB$$b0b63bb6
,但是outerServiceProxy
似乎直接调用String getRemoteHourRoomStatus()
而不是通过回调并调用TargetSource,因此service
为null。但这没有意义!当我添加public修饰符时,
public String getRemoteHourRoomStatus()
一切正常。更奇怪的是,没有
public
修饰符,相同的代码在我的PC上运行正常,但是在公司测试环境中抛出了NPE。 最佳答案
这是窍门:如果覆盖的类由与定义覆盖的方法的类相同的ClassLoader
加载,则VM仅认为包专用方法被覆盖。
这意味着对于两个具有覆盖的包专用方法的类,例如:
public class Foo { String qux() { return "foo"; } }
public class Bar extends Foo { @Override String qux() { return "bar"; } }
哪里
Foo.class.getClassLoader() != Bar.class.getClassLoader()
成立,可以观察到以下行为:
Foo foo = new Bar();
assertThat(foo.qux(), is("foo"));
assertThat(((Bar) foo).qux(), is("bar"));
原因是运行时程序包不相等,因此,不同运行时程序包的程序包专用方法不会相互覆盖。这对cglib的限制比对JVM的规范细节要少。