简体   繁体   中英

Service bean failed to inject in spring cglib proxy

I have an annotation

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PartnerProxy {
}

And a Advice

@Component
@Aspect
public class AnnotationAdvice {

    @Around("@annotation(PartnerProxy)")
    public Object pc(ProceedingJoinPoint joinPoint) throws Throwable {
        return joinPoint.proceed();
    }
}

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

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>

and when outerServiceProxy.getRemoteHourRoomStatus() method is called, An NPE was thrown. I debug to that line [1]

String getRemoteHourRoomStatus(){
        return service.echo();  [1]
    } 

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!

When i add public modifier, public String getRemoteHourRoomStatus() everything goes fine.

And even more strange thing is that without public modifer, same code goes well in my PC, but NPE thrown in company testing environment.

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"; } }

where

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"));

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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