服务 bean 在 spring cglib 代理中注入失败 [英] Service bean failed to inject in spring cglib proxy

查看:163
本文介绍了服务 bean 在 spring cglib 代理中注入失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个注释

@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 为空.但是 outerServiceProxyOuterServiceProxy$$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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆