Spring 容器AOP的實現原理——動態代理


參考:http://wiki.jikexueyuan.com/project/ssh-noob-learning/dynamic-proxy.html(from極客學院

 

一、介紹

Spring的動態代理有兩種:一是JDK的動態代理;另一個是cglib動態代理(通過修改字節碼來實現代理)。

今天主要討論JDK動態代理的方式。

JDK的代理方式主要就是通過反射跟動態編譯來實現的,主要搭配InvocationHandler和Proxy來實現,下面的例子中使用了兩層代理(即代理上加了一層代理)。

 

二、實例

1. 公共接口

1 package com.tgb.proxy;
2 
3 public interface UserMgr {
4 
5     void addUser();
6     void delUser();
7     
8 }

 

2. 實現類

 1 package com.tgb.proxy;
 2 
 3 public class UserMgrImpl implements UserMgr {
 4 
 5     @Override
 6     public void addUser() {
 7         System.out.println("添加用戶....");
 8     }
 9 
10     @Override
11     public void delUser() {
12         System.out.println("刪除用戶.....");
13     }
14 
15 }

 

3. TransactionHandler(InvocationHandler的實現)

 1 package com.tgb.proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 
 6 public class TransactionHandler implements InvocationHandler {
 7 
 8     private Object target;
 9     
10     public TransactionHandler(Object target){
11         super();
12         this.target = target;
13     }
14 
15     @Override
16     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
17         
18         System.out.println("開啟事務...");
19         
20         method.invoke(target);
21         
22         System.out.println("提交事務...");
23         
24         return null;
25     }
26     
27 
28 }

 

4. TimeHandler(InvocationHandler的實現)

 1 package com.tgb.proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.util.Calendar;
 6 
 7 public class TimeHandler implements InvocationHandler {
 8 
 9     private Object target;
10 
11     public TimeHandler(Object target) {
12         super();
13         this.target = target;
14     }
15 
16     @Override
17     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
18 
19         Calendar calendar = Calendar.getInstance();
20 
21         System.out.println("start time:" + calendar.get(Calendar.HOUR_OF_DAY));
22 
23         method.invoke(target);
24 
25         System.out.println("end time:" + calendar.get(Calendar.HOUR_OF_DAY));
26 
27         return null;
28     }
29 
30 }

 

5. 測試類

 1 package com.tgb.proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Proxy;
 5 
 6 public class Client {
 7 
 8     public static void main(String[] args) {
 9 
10         UserMgr userMgr = new UserMgrImpl();
11 
12         // 1.第一層代理----------通過動態代理,添加事務處理
13         InvocationHandler handler = new TransactionHandler(userMgr);
14         UserMgr userMgrProxy = (UserMgr) Proxy.newProxyInstance(userMgr.getClass().getClassLoader(),
15                 userMgr.getClass().getInterfaces(), handler);
16 
17         // 2.第二層代理----------通過動態代理,添加時間處理
18         InvocationHandler handler2 = new TimeHandler(userMgrProxy);
19         UserMgr userMgrProxy2 = (UserMgr) Proxy.newProxyInstance(userMgrProxy.getClass().getClassLoader(),
20                 userMgrProxy.getClass().getInterfaces(), handler2);
21 
22         userMgrProxy2.addUser();
23 
24         System.out.println("========================================");
25 
26         userMgrProxy2.delUser();
27 
28     }
29 }

 

輸出結果:

start time:Tue Aug 09 23:54:54 CST 2016
開啟事務...
添加用戶....
提交事務...
end time:Tue Aug 09 23:54:54 CST 2016
========================================
start time:Tue Aug 09 23:54:54 CST 2016
開啟事務...
刪除用戶.....
提交事務...
end time:Tue Aug 09 23:54:54 CST 2016

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM