问题
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.
回答1:
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.
来源:https://stackoverflow.com/questions/35135499/service-bean-failed-to-inject-in-spring-cglib-proxy