ChatGPT解决这个技术问题 Extra ChatGPT

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?

Get the code here : <gist.github.com/ksauzz/1563486>. In cglib you can create both class proxy and interface proxy. Spring uses CGlib by default while AspectJ uses Java proxy. Read this as well : jnb.ociweb.com/jnb/jnbNov2005.html ;)
@SubhadeepRay, I know your comment is very old, but I just saw it today. Sorry to correct you, but your statement "Spring uses CGlib by default while AspectJ uses Java proxy" is wrong for two reasons: (1) AspectJ does not use any proxies at all. (2) Spring Core by default uses JDK proxies for interfaces and CGLIB proxies for classes. Optionally, it can use CGLIB for interfaces, too. Spring Boot seems to always use CGLIB due to an unfortunate combination of config classes, but Boot is not Spring Core.

r
raphaëλ

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.


tHANKS..!! but it would be helpful if you could give me one example code(or Link) to illustrate one's usage over another in some case..!!!
Note that JDK proxies are actually ceating the proxy for IFoo not for any kind of Foo for at all. It's a rather important distinction. Also, cglib proxies are full subclasses -- take advantage of that! Use filters to only proxy methods you care about and use the generated class directly.
It should also be noted that CGLib sub class creation requires knowing enough about the super class to be able to call the correct constructor with the right args. Unlike interface based proxy which don't care about constructors. This makes working with CGLib proxies less "automatic" than JDK proxies. Another distinction is in the "stack" cost. A JDK proxy always incurs extra stack frames per call while a CGLib may not cost any extra stack frames. This becomes increasingly relevant the more complex the app gets (because the larger the stack, the more memory threads consume).
cglib cannot proxy final methods, but will not throw exception gist.github.com/mhewedy/7345403cfa52e6f47563f8a204ec0e80
Yes, CGLIB simply ignores final methods.
R
Rafael Winterhalter

Differences in functionality

The JDK proxies allow to implement any set of interfaces while subclassing Object. Any interface method, plusObject::hashCode, Object::equals and Object::toString is then forwarded to an InvocationHandler. Additionally, the standard library interface java.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 a MethodInterceptor. Furthermore, cglib can improve performance by specialized interceptions like FixedValue. 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.


Why does spring documentation favor JDK proxying over cglib given the performance benefits of the latter? docs.spring.io/spring/docs/2.5.x/reference/…
Cglib is an external dependeny and currently unsupported. Relying on third-party software is always a gamble so its best when as few people as possible rely on it.
In your blog you say: "However, you should be careful when calling a method on the proxy object that comes with the InvocationHandler#invoke method. All calls on this method will be dispatched with the same InvocationHandler and might therefore result in an endless loop." What do you mean?
If you call a method on the proxy object, any call is routed through ,our invocation handler. If any invocation handler call delegates to a call to the object, mentioned recursion happens.
Hi Rafael, message unrelated to your answer, I'm pinging you about an edit made 5 years ago. As cglib apparently still has commits in 2019, and doesn't show any arrested development in its readme, I've removed your statement from the tag excerpt. Feel free to improve the tag description/excerpt if there is anything relevant to mention.
P
Premraj

Dynamic proxy: Dynamic implementations of interfaces at runtime using JDK Reflection API.

Example: Spring uses dynamic proxies for transactions as follows:

https://i.stack.imgur.com/CigPu.png

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:

https://i.stack.imgur.com/fsOVh.png

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


b
bernie

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.