1. What is CGLIB?
CGLIB is a powerful, high-performance code generation package. It provides proxies for classes that do not implement interfaces, and provides a good supplement to JDK's dynamic proxy. Usually you can use Java's dynamic proxy to create proxies, but when the class to be proxied does not implement an interface or for better performance, CGLIB is a good choice.
As an open-source project, CGLIB's code is hosted on GitHub at:https://github.com/cglib/cglib
2. CGLIB Principle
CGLIB principle: Dynamically generates a subclass of the class to be proxied, and the subclass overrides all non-final methods of the class to be proxied. In the subclass, method interception technology is used to intercept all calls to parent class methods, and cross-cutting logic is woven in accordingly. It is faster than JDK dynamic proxy using Java reflection.
CGLIB underlying layer: It uses the bytecode processing framework ASM to transform bytecode and generate new classes. Direct use of ASM is discouraged because it requires you to be very familiar with the JVM internal structure, including the format of class files and the instruction set.
CGLIB disadvantages: Final methods cannot be proxied.
3. CGLIB Applications
It is widely used by many AOP frameworks, such as Spring AOP and dynaop. Hibernate uses CGLIB to proxy single-ended (many-to-one and one-to-one) associations.
4. Why Use CGLIB?
CGLIB proxy mainly operates on bytecode to introduce an indirection level for objects, in order to control access to objects. We know that Java has a dynamic proxy that also does this, so why not directly use Java dynamic proxy and instead use CGLIB? The answer is that CGLIB is more powerful than JDK dynamic proxy. Although JDK dynamic proxy is simple and easy to use, it has a fatal flaw: it can only proxy interfaces. If the class to be proxied is an ordinary class without an interface, then Java dynamic proxy cannot be used.
5. CGLIB Composition Structure

CGLIB's underlying layer uses ASM (a compact and powerful bytecode manipulation framework) to operate on bytecode and generate new classes. In addition to the CGLIB library, scripting languages (such as Groovy and BeanShell) also use ASM to generate bytecode. ASM uses a SAX-like parser to achieve high performance. We do not encourage direct use of ASM because it requires sufficient understanding of the Java bytecode format.
6. CGLIB API
1. Jar package:
- cglib-nodep-2.2.jar: When using the nodep package, there is no need to associate the ASM jar package; the jar package contains ASM classes internally.
- cglib-2.2.jar: When using this jar package, you need to associate the ASM jar package; otherwise, a runtime error will occur.
2. CGLIB library:
Since the underlying code is minimal, it is somewhat difficult to learn, mainly due to the lack of documentation and examples, which is also a shortcoming of CGLIB.
The CGLIB version used in this series is 2.2.
- net.sf.cglib.core: Low-level bytecode processing classes, most of which are related to ASM.
- net.sf.cglib.transform: Transformation of classes and class files at compile time or runtime
- net.sf.cglib.proxy: Classes that implement proxy creation and method interceptors
- net.sf.cglib.reflect: Classes that implement fast reflection and C#-style proxies
- net.sf.cglib.util: Utility classes such as collection sorting
- net.sf.cglib.beans: Utility classes related to JavaBean
This article introduces implementing a dynamic proxy through MethodInterceptor and Enhancer.
1. First, let's talk about the dynamic proxy in JDK:
The dynamic proxy in JDK is implemented through the reflection class Proxy and the InvocationHandler callback interface. However, the class to be dynamically proxied in JDK must implement an interface. That is to say, only methods defined in the interface implemented by the class can be proxied. This has certain limitations in actual programming, and the efficiency of using reflection is not very high.
2. Using CGLib to implement:
Using CGLib to implement dynamic proxy is completely free from the restriction that the proxy class must implement an interface. Moreover, CGLib's underlying layer uses the ASM bytecode generation framework to generate proxy classes using bytecode technology, which is more efficient than using Java reflection. The only thing to note is that CGLib cannot proxy methods declared as final, because the principle of CGLib is to dynamically generate a subclass of the proxied class.
Below, an example is used to introduce the implementation of dynamic proxy using CGLib.
1. Proxied class:
First, define a class that does not implement any interface.
2. Interceptor:
Define an interceptor. When the target method is called, CGLib will call back the MethodInterceptor interface method for interception to implement your own proxy logic, similar to the InvocationHandler interface in JDK.
Parameters: Object is the proxy class instance dynamically generated by CGLib, Method is the reference to the proxied method called by the entity class above, Object[] is the list of parameter values, and MethodProxy is the proxy reference to the method generated by the proxy class.
Return: The value returned from the method call on the proxy instance.
Among them,proxy.invokeSuper(obj,arg)Invoke the superclass method of the proxy method on the proxy class instance (i.e., the corresponding method in the entity class TargetObject).
In this example, only one sentence is printed before and after calling the proxied class method. Of course, in actual programming, it can be other complex logic.
3. Generate the dynamic proxy class:
Here, the Enhancer class is a bytecode enhancer in CGLib. It can conveniently extend the class you want to process, and we will see it often later.
First set the proxied class TargetObject as the parent class, then set the interceptor TargetInterceptor, and finally execute enhancer.create() to dynamically generate a proxy class, and cast it from Object to the parent type TargetObject.
Finally, call the method on the proxy class.
4. Callback filter CallbackFilter
1. Function:
When CGLib performs callbacks, you can set different callback logic for different methods, or even not perform callbacks at all.
There is no similar feature in JDK dynamic proxy; the call to the InvocationHandler interface method is effective for all methods in the proxy class.
Define a class that implements the CallbackFilter interface:
The return value is the position index of each method of the proxied class in the callback array Callback[] (see below).
5. Lazy loading objects
1. Function:
Speaking of lazy loading, you should often encounter it, especially when using Hibernate. This article will analyze the implementation of lazy loading through an example. The LazyLoader interface inherits Callback, so it is also a type of Callback in CGLib.
Another lazy loading interface is Dispatcher.
The Dispatcher interface also inherits from Callback and is also a type of callback.
But the difference between Dispatcher and LazyLoader is: LazyLoader only triggers the proxy class callback method when the lazy-loaded property is accessed for the first time, while Dispatcher triggers the proxy class callback method every time the lazy-loaded property is accessed.
II. Example:
First, define an entity class LoaderBean. This Bean has a property PropertyBean that needs lazy loading.
6. InterfaceMaker - Interface Generator
I. Function:
InterfaceMaker dynamically generates an interface that contains all methods defined by the specified class.
II. Example:
Original address:
https://blog.csdn.net/zghwaicsdn/article/details/50957474
https://blog.csdn.net/danchu/article/details/70238002