服务 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
And the bean i want to proxy
public class OuterServiceProxy {
private IRoomStatusService service;
... another properties
String getRemoteHourRoomStatus(){
return service.echo();
}
@PartnerProxy
public void hello() {
}
...getters & setters
有一个属性IRoomStatusService service
,这就是重点.首先,如果我在 spring xml 文件中声明 OuterServiceProxy
there is a property IRoomStatusService service
, which is the point.
firstly if i declare OuterServiceProxy
in spring xml file
<bean id="outerServiceProxy" class="aop.jg.OuterServiceProxy">
<property name="service" ref="service"/>
</bean>
当 outerServiceProxy.getRemoteHourRoomStatus()
方法被调用时,一个 NPE 被抛出.我调试到那一行 [1]
and when outerServiceProxy.getRemoteHourRoomStatus()
method is called, An NPE was thrown. I debug to that line [1]
String getRemoteHourRoomStatus(){
return service.echo(); [1]
}
service
为空.但是 outerServiceProxy
是 OuterServiceProxy$$EnhancerByCGLIB$$b0b63bb6
实际上是由 Cglib 增强的,但看起来 outerServiceProxy
只是调用 String getRemoteHourRoomStatus()
直接而不是通过回调和调用 TargetSource,所以 service
为空.但这毫无意义!
service
is null. But outerServiceProxy
is OuterServiceProxy$$EnhancerByCGLIB$$b0b63bb6
actually enhanced by Cglib, but it seems outerServiceProxy
just call String getRemoteHourRoomStatus()
directly and not through callback and call TargetSource, So service
is null. But that make no sense!
当我添加 public 修饰符时,public String getRemoteHourRoomStatus()
一切正常.
When i add public modifier, public String getRemoteHourRoomStatus()
everything goes fine.
更奇怪的是,如果没有 public
修饰符,同样的代码在我的电脑上运行良好,但在公司测试环境中抛出了 NPE.
And even more strange thing is that without public
modifer, same code goes well in my PC, but NPE thrown in company testing environment.
推荐答案
这里有诀窍:如果覆盖类由相同的 ClassLoader
作为定义重写方法的类.
Here is the trick: The VM only consideres a package-private method to be overridden if the overriding class is loaded by the same ClassLoader
as the class the defines the overridden method.
这意味着对于具有重写包私有方法的两个类,例如:
This means that for two classes with overridden package-private methods such as:
public class Foo { String qux() { return "foo"; } }
public class Bar extends Foo { @Override String qux() { return "bar"; } }
哪里
Foo.class.getClassLoader() != Bar.class.getClassLoader()
成立,可以观察到以下行为:
holds, the following behavior can be observed:
Foo foo = new Bar();
assertThat(foo.qux(), is("foo"));
assertThat(((Bar) foo).qux(), is("bar"));
原因是运行时包不相等,因此不同运行时包的包私有方法不会相互覆盖.这与其说是 cglib 的限制,不如说是 JVM 的规范细节.
The reasoning is that the runtime packages are not equal and therefore, the package-private methods of differing runtime packages do not override one another. This is less a limitation of cglib than a specification detail of the JVM.
这篇关于服务 bean 在 spring cglib 代理中注入失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!