What is the difference between JDK dynamic proxy and CGLib?
In case of the Proxy Design Pattern, What is the difference between JDK's Dynamic Proxy and third party dynamic code generation API s such as CGLib?
What is the difference between using both the approaches and when should one prefer one over another?
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.
Differences in functionality
The JDK proxies allow to implement any set of interfaces while subclassing
Object
. Any interface method, plusObject::hashCode
,Object::equals
andObject::toString
is then forwarded to anInvocationHandler
. Additionally, the standard library interfacejava.lang.reflect.Proxy
is implemented.cglib allows you to implement any set of interfaces while subclassing any non-final class. Also, methods can be overridden optionally, i.e. not all non-abstract methods need to be intercepted. Furthermore, there are different ways of implementing a method. It also offers an
InvocationHandler
class (in a different package), but it also allows to call super methods by using more advanced interceptors as for example aMethodInterceptor
. Furthermore, cglib can improve performance by specialized interceptions likeFixedValue
. I once wrote a summary of different interceptors for cglib.
Performance differences
JDK proxies are implemented rather naively with only one interception dispatcher, the InvocationHandler
. This requires a virtual method dispatch to an implementation which cannot always be inlined. Cglib allows to create specialized byte code what can sometimes improve performance. Here are some comparisons for implementing an interface with 18 stub methods:
cglib JDK proxy
creation 804.000 (1.899) 973.650 (1.624)
invocation 0.002 (0.000) 0.005 (0.000)
The time is noted in nanoseconds with standard deviation in braces. You can find more details on the benchmark in Byte Buddy's tutorial, where Byte Buddy is a more modern alternative to cglib. Also, note that cglib is no longer under active development.
Dynamic proxy: Dynamic implementations of interfaces at runtime using JDK Reflection API.
Example: Spring uses dynamic proxies for transactions as follows:
The generated proxy comes on top of bean. It adds transnational behavior to the bean. Here the proxy generates dynamically at runtime using JDK Reflection API.
When an application is stopped, the proxy will be destroyed and we will only have interface and bean on the file system.
In the above example we have interface. But in most of implementation of interface is not best. So bean does not implement an interface, in that case we uses inheritance:
In order to generate such proxies, Spring uses a third party library called CGLib.
CGLib (Code Generation Library) is built on top of ASM, this is mainly used the generate proxy extending bean and adds bean behavior in the proxy methods.
Examples for JDK Dynamic proxy and CGLib
Spring ref
From Spring documentation :
Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxy for a given target object. (JDK dynamic proxies are preferred whenever you have a choice).
If the target object to be proxied implements at least one interface then a JDK dynamic proxy will be used. All of the interfaces implemented by the target type will be proxied. If the target object does not implement any interfaces then a CGLIB proxy will be created.
If you want to force the use of CGLIB proxying (for example, to proxy every method defined for the target object, not just those implemented by its interfaces) you can do so. However, there are some issues to consider:
final methods cannot be advised, as they cannot be overriden.
You will need the CGLIB 2 binaries on your classpath, whereas dynamic proxies are available with the JDK. Spring will automatically warn you when it needs CGLIB and the CGLIB library classes are not found on the classpath.
The constructor of your proxied object will be called twice. This is a natural consequence of the CGLIB proxy model whereby a subclass is generated for each proxied object. For each proxied instance, two objects are created: the actual proxied object and an instance of the subclass that implements the advice. This behavior is not exhibited when using JDK proxies. Usually, calling the constructor of the proxied type twice, is not an issue, as there are usually only assignments taking place and no real logic is implemented in the constructor.