简体   繁体   中英

Different between CGLIB proxy and JDK proxy on Spring AOP perspective

Baeldung has this section:

this limits matching to join points where the bean reference is an instance of the given type, while target limits matching to join points where the target object is an instance of the given type. The former works when Spring AOP creates a CGLIB-based proxy, and the latter is used when a JDK-based proxy is created. Suppose that the target class implements an interface:

public class FooDao implements BarDao {
    ...
}

In this case, Spring AOP will use the JDK-based proxy, and we should use the target PCD because the proxied object will be an instance of the Proxy class and implement the BarDao interface:

@Pointcut("target(com.baeldung.pointcutadvice.dao.BarDao)")

On the other hand, if FooDao doesn't implement any interface, or the proxyTargetClass property is set to true, then the proxied object will be a subclass of FooDao and we can use the this PCD:

@Pointcut("this(com.baeldung.pointcutadvice.dao.FooDao)")

I'm still confuse why this just works with CGLIB proxy and target just works with JDK proxy. Could you help to tell me the different between them?

Actually, the explanation in the tutorial does not make much sense:

  • Both this(MyInterface) and target(MyInterface) work for JDK proxies, if the bean is declared as a MyInterface type.
  • Both this(MyClass) and target(MyClass) work for CGLIB proxies, if the bean is declared as a MyClass type.

Just try, and you will see that I am right. In Spring AOP, there is not real difference between this() and target() , because due to its proxy-based nature, it implicitly only supports execution() pointcuts from AspectJ.

In native AspectJ however, you also have other pointcut types such as call() , and there you would see a difference: this() would match the caller's type, while target() would match the callee's type. Eg, if you intercept a method Aa() calling Bb() via pointcut call(Bb()) , this() would return an A instance, while target() would return a B instance. Do not worry, if this is difficult to understand for you, because for Spring AOP and execution pointcuts it really does not matter.

The only subtle difference I noticed in Spring AOP is, that for MyInterfaceImpl implements MyInterface , pointcut target(MyInterfaceImpl) would actually match, while this(MyInterfaceImpl) would not. This is because for JDK proxies, the proxy actually extends java.lang.reflect.Proxy , not MyInterfaceImpl . The proxy only delegates to a MyInterfaceImpl instance. I would have to write a lot in order to explain the semantics here, but I do not want to make the matter even more complicated.

Bottom line: For all intents and purposes, in normal use cases you can use either this() or target() for both JDK and CGLIB proxies. I recommend to stick with target() , because it best matches the implicit execution() semantics of Spring AOP.

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