This article has participated in the third “topic writing” track of the Denver Creators Training Camp. For details, check out: Digg Project | Creators Training Camp third is ongoing, “write” to make a personal impact.
Spring’s AOP dynamic proxy is implemented in two ways, the JDK implementation and the CGLIB implementation. What is the difference?
The difference between
While dynamic proxies in the JDK implement interfaces, CGLIB creates subclasses that operate outside the methods of its parent class.
- JDK proxy classes are used if the class is an interface or a proxy class created by the JDK
- Non-interface classes use the CGLib proxy, or proxyTargetClass = true in configuration annotations
Performance comparison of the two:
Core code location
JDK dynamic proxy principles
JDK dynamic proxies are implemented primarily through the Porxy class and the InvokationHandler interface in the reflection package. Together, they create dynamic proxy classes. The Porxy class creates dynamic proxy classes based on passed parameters. InvokationHandler is used to fire the methods of the dynamic proxy class. This process is dynamically generated and processed during program execution, so it is called dynamic proxy.
The code is as follows:
Porxy class
The Porxy class provides a static method for creating dynamic proxy classes.
public static Object newProxyInstance(ClassLoader loader, Class
[] interfaces, InvocationHandler h)
throws IllegalArgumentException
Copy the code
1, ClassLoader: ClassLoader will define the dynamic proxy class, ClassLoader can be obtained through the class or interface, if we want to obtain through the interface, call the method as follows.
Task.class.getClassLoader()
Copy the code
If we get it from a class, we have a TaskImpl class that implements the Task interface, we have a TaskImpl object ob, and the ClassLoader gets it as follows
ob.getClassLoader()
Copy the code
2, Class <? >[] interfaces: interfaces that dynamic proxy classes need to implement
InvocationHandler: Pass an instance of a class that implements the InvokationHandler interface
InvokationHandler
InvokationHandler is an interface in the Java reflection package. The InvokationHandler is implemented through the user class to fire a dynamic proxy class method. It has only one method:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
Copy the code
1. Object: the proxy Object that implements the Method. 2. Method: the Method that the proxy instance fires, the interface Method in the Porxy parameter
implementation
1. We provide an interface
package me.aihe;
public interface Task {
void setData(String data);
int getCalData(int x);
}
Copy the code
2. Implement this interface
package me.aihe; public class TaskImpl implements Task { @Override public void setData(String data) { System.out.println(data+ " Data is saved"); } @Override public int getCalData(int x) { return x * 10; }}Copy the code
3. Define your own InvokationHandler class and implement the Invoke method of the InvokationHandler interface
package me.aihe; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class MyInvokationHandler implements InvocationHandler { private Object obj; public MyInvokationHandler(Object object){ this.obj = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result; if(method.getName().contains("get")){ System.out.println("... get Method Executing..." ); }else{ System.out.println("... set Method Executing..." ); } result = method.invoke(obj, args); return result; }}Copy the code
Create a factory class to get the dynamic proxy class:
package me.aihe;
import java.lang.reflect.Proxy;
public class ProxyFactory {
public static Object newInstance(Object ob) {
return Proxy.newProxyInstance(ob.getClass().getClassLoader(),
new Class<?>[] { Task.class }, new MyInvokationHandler(ob));
}
}
Copy the code
5. Provide our test classes
package me.aihe;
public class Test {
public static void main(String[] args) {
Task task = (Task)ProxyFactory.newInstance(new TaskImpl());
task.setData("Test");
System.out.println("============");
System.out.println(task.getCalData(5));
}
}
Copy the code
See the output of the program:
...set Method Executing...
Test Data is saved
============
...get Method Executing...
50
Copy the code
CGLIB code example
Here is how to use it.
1. Create a service class
The introduction of Maven:
<! -- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> < artifactId > additional < / artifactId > < version > 3.3.0 < / version > < / dependency >Copy the code
package cglib.enhancer;
public class Hello {
public String sayHello(boolean throwException) throws Exception {
System.out.println("hello everyone!");
if(throwException)
throw new Exception("test exception");
return "123";
}
}
Copy the code
Implement the MethodInterceptor interface
package cglib.enhancer; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; Public class ProxyFactory implements MethodInterceptor {// Private Object obj; public Object createProxy(Object target) { this.obj = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.obj.getClass()); // Set the proxy target, enhancer.setcallback (this); SetClassLoader (target.getClass().getClassLoader())); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object result = null; Try {// before(); result = proxy.invokeSuper(obj, args); // after(); } catch (Exception e) { exception(); }finally{ beforeReturning(); } return result; } private void before() { System.out.println("before method invoke"); } private void after() { System.out.println("after method invoke"); } private void exception() { System.out.println("method invoke exception"); } private void beforeReturning() { System.out.println("before returning"); }}Copy the code
Dynamic proxy
package cglib.enhancer; public class EnhancerTest { public static void main(String[] args) throws Exception { Hello hello = new Hello(); ProxyFactory cglibProxy = new ProxyFactory(); Hello proxy = (Hello) cglibProxy.createProxy(hello); String result=proxy.sayHello(true); System.out.println(result); }}Copy the code