服务 bean 无法注入 spring cglib 代理
Service bean failed to inject in spring cglib proxy
我有注释
@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();
}
}
以及我要代理的 bean
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
修改器,同样的代码在我的电脑上运行良好,但在公司测试环境中抛出NPE。
诀窍是:如果重写 class 由与定义重写的方法。
这意味着对于两个 class 具有覆盖包私有方法的 es,例如:
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 的规范细节。
我有注释
@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();
}
}
以及我要代理的 bean
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
修改器,同样的代码在我的电脑上运行良好,但在公司测试环境中抛出NPE。
诀窍是:如果重写 class 由与定义重写的方法。
这意味着对于两个 class 具有覆盖包私有方法的 es,例如:
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 的规范细节。