There are two proxy classes, based on when the agent was created. Static proxy: source code created by a programmer or automatically generated by a specific tool and then compiled. The.class file for the proxy class exists before the program runs. Dynamic proxy: dynamically created using reflection while the program is running.
Dynamic proxy can be used in three ways
Dynamic proxies can be implemented in three ways: JDK dynamic proxies (based on interfaces), Cglib dynamic proxies (based on inheritance), and Javassist (used in Hibernate).
JDK implementation of dynamic proxy requires implementation classes to define business methods through interfaces. For classes without interfaces, how to implement dynamic proxy? That’s where CGLib comes in.
How does CGLIb implement proxying
Cglib is an excellent dynamic proxy framework, its bottom layer uses ASM to dynamically generate the proxied class subclass in memory, using Cglib even if the proxy class does not implement any interface can also achieve dynamic proxy function.
The principle of CGLib is to create a subclass of a class using bytecode technology, and use method interception technology in the subclass to intercept all calls to the parent class method, which is woven into crosscutting logic.
Dynamic proxy objects created by CGLib perform much better than those created by JDK. However, CGLib takes much longer to create proxy objects than the JDK, so for singleton objects, CGLib works better than JDK because you don’t need to create objects frequently. At the same time, because CGLib is subclassed dynamically, there is no proxy for final methods.
CgLib dynamic proxy instance
Here is an example of a dynamic proxy.
Importing Maven dependencies
Cglib is based on ASM byte modification technology. Importing Cglib directly imports three JARS: ASM, Ant, and ant-Launcher.
<! Begin --> <dependency> <groupId>cglib</groupId> <artifactId> The < version > 3.2.5 < / version > < / dependency > <! -- Cglib dynamic proxy dependency stop -->Copy the code
The core classes of CGLIB:
- Net. Sf. Additional. Proxy. Enhancer – the main enhancement class
- .net. Sf. Additional. Proxy. MethodInterceptor interceptor class – the main method, it is a Callback interface son interface, users need
- .net. Sf. Additional. Proxy. MethodProxy – the Java JDK. Lang. Reflect. The Method of class proxy class, can easily realize the source object Method invocation, such as using:
- Object o = methodProxy.invokeSuper(proxy, args); // Even though the first argument is the propped object, there is no problem with an infinite loop.
Implement a business class that does not implement any interface:
Public class HelloService {public HelloService() {system.out.println ("HelloService construct "); } public void sayHello() { System.out.println("HelloService:sayHello"); }Copy the code
Net. Sf. Additional. Proxy. MethodInterceptor interface is the most common type of callback, the callback, it is often proxy-based AOP is used to implement interception (intercept) method is called. Public Object Intercept (Object Object, java.lang.reflect.Method Method,Object[] args, MethodProxy proxy) throws Throwable;
The MethodInterceptor implements the MethodInterceptor interface:
Public class HelloServiceInterceptor implements MethodInterceptor{/** * sub: cglib generated proxy object * method: proxied method * objects: Method entry parameter * methodProxy: Override public Object Intercept (Object sub, Method Method, Object[] objects, MethodProxy MethodProxy) throws Throwable {system.out. println("====== inserts pre-notification ======"); Object object = methodProxy.invokeSuper(sub, objects); System.out.println("====== insert post-notification ======"); return object; }Copy the code
Test class, generate CGLIB proxy object to call target method:
Public class CglibTest {public static void main(String[] args) {Enhancer Enhancer = new Enhancer(); // Set the parent class of the enhancer object to enhancer.setsuperclass (helloService.class); // Set the enhancer callback object, enhancer.setCallback(new HelloServiceInterceptor()); HelloService proxy= (HelloService)enhancer.create(); // Call the target method proxy.sayHello() from the proxy object; }}Copy the code
Additional summary
- CGlib can be passed either to an interface, which uses implementation, or to a normal class, which uses inheritance to generate proxy classes.
- Methods described by static methods,private methods, and final methods cannot be propped because of inheritance
- Method access optimization has been made to create Method indexes to avoid the need for traditional JDK dynamic proxies to be called through Method reflection.
- Provides callback and filter designs that flexibly bind different callbacks to different methods. Coding is more convenient and flexible.
- Additional will default equals in the agent Object, toString, hashCode, clone and other methods. More Clones than JDK proxies.
Follow the public account: Architecture evolution, get first hand technical information and original articles