Differencebetween Jdk Dynamic Proxy and Cglib

What is the difference between JDK dynamic proxy and CGLib?

JDK Dynamic proxy can only proxy by interface (so your target class needs to implement an interface, which is then also implemented by the proxy class).

CGLIB (and javassist) can create a proxy by subclassing. In this scenario the proxy becomes a subclass of the target class. No need for interfaces.

So Java Dynamic proxies can proxy: public class Foo implements iFoo where CGLIB can proxy: public class Foo

EDIT:

I should mention that because javassist and CGLIB use proxy by subclassing, that this is the reason you cannot declare final methods or make the class final when using frameworks that rely on this. That would stop these libraries from allowing to subclass your class and override your methods.

Different between CGLIB proxy and JDK proxy on Spring AOP perspective

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. E.g., if you intercept a method A.a() calling B.b() via pointcut call(B.b()), 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.


Edit: If you keep in mind that, in contrast to native AspectJ which involves no dynamic proxies, the semantics in Spring AOP are such that

  • this() relates to the proxy object, while
  • target() relates to the proxied object (proxy target),

it becomes clear why in this special case for JDK proxies target() matches, but this() does not.

Reference: Spring manual, section "Declaring a pointcut - examples":

this(com.xyz.service.AccountService): Any join point (method execution only in Spring AOP) where the proxy implements the AccountService interface.

target(com.xyz.service.AccountService): Any join point (method execution only in Spring AOP) where the target object implements the AccountService interface.

Only in this case, we are not asking for the interface class (which both the proxy and the target object implement), but for the implementation class itself.


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, and usually you are interested in information about the target rather than about the proxy..

Spring JDK Dynamic Proxy and CGLIB - implementation details

The behavior of the Cglib-proxies has nothing to do with the way of how cglib works but with how cglib is used by Spring. Cglib is capable of either delegating or subclassing a call. Have a look at Spring's DynamicAdvisedInterceptor which implements this delegation. Using the MethodProxy, it could instead perform a super method call.

Spring defines delegation rather than subclassing in order to minimize the difference between using Cglib or Java proxies. This is simply a choice made.

why spring AOP use JDK Dynamic proxy?

Converting my comments into an answer...

User R.G said:

This SO Q&A provides a lot of insights on the topic.

The accepted answer is not very helpful, but Rafael's comment under his own answer explains it: "Cglib is an external dependeny (...) Relying on third-party software is always a gamble, so it is best when as few people as possible rely on it." I.e., if you have a Spring application with very clean design, always programming against interfaces instead of directly against classes, you do not need CGLIB at all.

Slightly off-topic, but FYI: For similar reasons, the Spock testing framework supports JDK interface proxies out of the box for users who only need interface mocks. In that case, the optional dependency CGLIB (or ByteBuddy) and special stuff like Objenesis are unnecessary. So, this kind of strategy is quite common.



Related Topics



Leave a reply



Submit