繁体   English   中英

服务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为空。 但是outerServiceProxyOuterServiceProxy$$EnhancerByCGLIB$$b0b63bb6实际上是由Cglib增强的,但似乎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的规范细节。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM