Two Realizations of Dynamic Agent

Posted by dawieharmse on Sun, 19 May 2019 03:36:35 +0200

Today is the weekend again, and my spring trick is almost over. I want to write something when I am bored.

I want to mention one thing first, for example, if you want to calculate the execution time of a piece of code, then you must have written it like this before.

1 /**
2  * Define an interface first
3  * 
4  * @author chang
5  */
6 public interface DoSomthing {
7 
8     void doSomthing() throws InterruptedException;
9 }
 1 /**
 2  * Implementation class
 3  * @author chang
 4  */
 5 public class DoSomthingImpl implements DoSomthing {
 6     
 7     @Override
 8     public void doSomthing() throws InterruptedException {
 9         Thread.sleep(100);
10         System.out.println("This is the subject's accommodation.  " + System.currentTimeMillis());
11         Thread.sleep(100);
12     }
13 }

 

Writing to death is also the most clumsy way.

Add before(), after() before and after doSomthing. These two methods. If there are other ways to execute befor, after, it's also written in the code.

 

This is the so-called static proxy, very troublesome and code is very redundant, so great dynamic proxy emerged.

 

JDK dynamic proxy:

 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 import java.lang.reflect.Proxy;
 4 
 5 public class JDKDynamicProxy implements InvocationHandler{
 6 
 7     Object o = null;
 8     
 9     public JDKDynamicProxy(Object o) {
10         this.o = o;
11     }
12     
13     public Object getProxy() {
14         
15         return Proxy.newProxyInstance(o.getClass().getClassLoader(), 
16                 o.getClass().getInterfaces(), this);
17     }
18     
19     @Override
20     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
21         
22         before();
23         Object res = method.invoke(o, args);
24         after();
25         return res;
26     }
27     
28     void before() {
29         System.out.println(System.currentTimeMillis());
30     }
31     
32     void after() {
33         System.out.println(System.currentTimeMillis());
34     }
35     
36 }
1 public class Test {
2     public static void main(String[] args) throws InterruptedException {
3         
4         JDKDynamicProxy jp = new JDKDynamicProxy(new DoSomthingImpl());
5         DoSomthing ds = (DoSomthing) jp.getProxy();
6         ds.doSomthing();
7     }
8 }

Will you find it very convenient to expand? jdk will automatically proxy this method by using only one new dynamic proxy class at a time and passing the object of the implementation class to it.

Every time you call the doSomthing method, it's very convenient to automatically execute the before and after methods.

However, there is a problem that the dynamic proxy provided by JDK can only proxy interfaces, but can not proxy classes without interfaces. Because your Proxy.newProxyInstance has to pass an interface parameter in the past, so what?

 

CGLib Dynamic Agent

 1 import java.lang.reflect.Method;
 2 import net.sf.cglib.proxy.Enhancer;
 3 import net.sf.cglib.proxy.MethodInterceptor;
 4 import net.sf.cglib.proxy.MethodProxy;
 5 
 6 public class CGLibDynamicProxy implements MethodInterceptor{
 7 
 8     public CGLibDynamicProxy() {}
 9     
10     public <T> Object getProxy(Class<T> cls) {
11         return Enhancer.create(cls, this);
12     }
13     
14     @Override
15     public Object intercept(Object target, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
16         
17         before();
18         Object res = proxy.invokeSuper(target, arg2);
19         after();
20         return res;
21     }
22     
23     void before() {
24         System.out.println(System.currentTimeMillis());
25     }
26     
27     void after() {
28         System.out.println(System.currentTimeMillis());
29     }
30 }
1 public class Test {
2     public static void main(String[] args) throws InterruptedException {
3         
4         CGLibDynamicProxy cg = new CGLibDynamicProxy();
5         DoSomthing ds = (DoSomthing) cg.getProxy(DoSomthingImpl.class);
6         ds.doSomthing();
7     }
8 }

 

Similarly, a new CGLibDynamicProxy object is obtained through the getProxy method, and then the method is directly invoked.

AOP at the bottom of the Spring framework is probably implemented in these two ways.

Topics: Java JDK Spring