Java learning: JDK dynamic proxy and CGLIB dynamic proxy, jdkcglib
The concept of proxy: A simple understanding is to create a proxy object for an object. Instead of directly referencing the original object, we create a proxy object to control reference to the original object.
Dynamic Proxy: dynamically generated by the Java reflection mechanism when the program is running, without manual coding. Dynamic proxy not only simplifies programming, but also improves the scalability of the software system, because the Java reflection mechanism can generate any type of dynamic proxy class.
Proxy principle: the proxy object contains a reference to the real object, which allows you to operate on the real object. At the same time, the proxy object provides the same interface as the real object so that it can replace the real object at any time. At the same time, the proxy object can append other operations when performing real object operations, which is equivalent to encapsulating real objects.
The following is a simple example to show how to implement proxies Based on JDK dynamic proxy and CGLIB.
Proxy interface UserService:
1 package com.liang.test;2 3 public interface UserService {4 public void say(String arg);5 }
UserService implementation class UserServiceImpl:
1 package com.liang.test;2 3 public class UserServiceImpl implements UserService {4 @Override5 public void say(String arg) {6 System.out.println("hello, I am " + arg);7 }8 }
JDK uses the Proxy class under the java. lang. reflect package and an InvocationHandler interface to generate dynamic Proxy classes and dynamic Proxy objects.
First create a call controller object that implements the InvocationHandler interface MyInvocationHandler :( when executing the target method in the dynamic proxy object, it will actually be replaced with the invoke method that calls MyInvocationHandler)
1 package com. liang. test; 2 3 import java. lang. reflect. invocationHandler; 4 import java. lang. reflect. method; 5 6 public class MyInvocationHandler implements InvocationHandler {// implements InvocationHandler 7 8 private Object object; // 9 10 public MyInvocationHandler (Object object Object) {// receive the proxy object 11 this. object = object; 12} 13 @ Override14 public Object invoke (Object proxy, Method method, Object [] args) 15 throws Throwable {// say () the method is replaced with the current method. You can add additional functions to the method to enhance the target. Method 16: System. out. println ("before method"); 17 Object obj = method. invoke (object, args); // call the say () method of UserService through reflection 18 System. out. println ("after method"); 19 return obj; 20} 21 22}
Use Proxy and MyInvocationHandler to create a dynamic Proxy class for UserService:
1 package com. liang. test; 2 3 import java. lang. reflect. invocationHandler; 4 import java. lang. reflect. proxy; 5 6 public class TestProxy {7 8 public static void main (String [] args) {9 UserService userService = new UserServiceImpl (); 10 InvocationHandler handler = new MyInvocationHandler (userService ); 11 12 UserService proxy = (UserService) Proxy. newProxyInstance (userService. getClass () 13. getClassLoader (), userService. getClass (). getInterfaces (), 14 handler); 15 proxy. say ("Sun Wukong"); // call proxy instance 16} 17 18}
Running result:
Before methodhello, I am Sun Wukong after method
You can see that the method of MyInvocationHandler invoke () is executed when you execute the say method of the proxy instance.
CGLIB uses the very underlying bytecode technology to create a subclass for the proxy object and uses the method Blocking Technology in the subclass to intercept calls of all parent methods, and install the enhanced code. An example of using CGLIB to implement dynamic proxy is as follows:
1 package com. liang. test; 2 3 import java. lang. reflect. method; 4 5 import net. sf. cglib. proxy. enhancer; 6 import net. sf. cglib. proxy. methodInterceptor; 7 import net. sf. cglib. proxy. methodProxy; 8 9 public class CglibProxy implements MethodInterceptor {10 11 private Enhancer enhancer = new Enhancer (); 12 13 public Object getProxy (Class clazz) {14 enhancer. setSuperclass (clazz); // set the class 15 enhancer. setCallback (this); 16 return enhancer. create (); // create a subclass instance 17} 18 19 @ Override20 public Object intercept (Object object Object, Method method, Object [] args, 21 MethodProxy proxy) throws Throwable {// intercept all methods in the parent class to call 22 System. out. println ("cglib: before method"); 23 Object obj = proxy. invokeSuper (object, args); // call the method in the parent class through the proxy class 24 System. out. println ("cglib: after method"); 25 return obj; 26} 27 28}
Test code:
1 package com. liang. test; 2 3 public class TestProxy {4 5 public static void main (String [] args) {6 CglibProxy proxy = new CglibProxy (); 7 UserServiceImpl userServiceImpl = (UserServiceImpl) proxy. getProxy (UserServiceImpl. class); 8 userServiceImpl. say ("Sun Wukong"); 9} 10 11}
Running result:
Cglib: before methodhello, I am Sun Wukong cglib: after method
Summary: The most common application of JDK dynamic proxy and CGLIB dynamic proxy is the underlying implementation of SpringAOP. JDK-based Dynamic proxy takes less time to create proxy objects than CGLIB, however, JDK can only create proxy instances for interfaces. This can be seen from newProxyInstance (ClassLoader loader, Class [] interfaces, InvocationHandler h: the second input parameter is the list of interfaces implemented by the proxy example. The performance of the proxy object created by CGLIB is higher than that created by JDK, but it takes a relatively long time. Besides, CGLIB uses dynamic subclass creation to generate the proxy object, therefore, Methods Modified by final cannot be proxy through CGLIB. Based on this, CGLIB dynamic proxy technology is suitable for singgleton proxy objects or proxies with instance pools. JDK dynamic proxy technology is generally used for new instances every time.
For more information, see:
1. Master Spring2.x-enterprise application development details-Chen xionghua;
2. http://rejoy.iteye.com/blog/1627405--jdkdynamic proxy Principle