設計模式之禪之代理模式

Love Lenka發表於2017-02-13

jdk的動態代理的條件:

===>要實現動態代理的首要條件是:被代理類必須實現一個介面,回想一下前面的分析吧。當然了,現在也有很多技術如CGLIB可以實現不需要介面也可以實現動態代理的方
式。

 

動態代理的應用

代理模式應用得非常廣泛,大到一個系統框架、企業平臺,小到程式碼片段、事務處理,稍不留意就用到代理模式。可能該模式是大家接觸最多的模式,而且有了AOP大家寫代理就
更加簡單了,有類似Spring AOP和AspectJ這樣非常優秀的工具,拿來主義即可!不過,大家可以看看原始碼,特別是除錯時,只要看到類似$Proxy0這樣的結構,你就應該知道這是一
個動態代理了。友情提醒,在學習AOP框架時,弄清楚幾個名詞就成:切面(Aspect)、切入點(JoinPoint)、通知(Advice)、織入(Weave)就足夠了,理解了這幾個名詞,應用時你
就可以遊刃有餘了!

 

(1)普通代理,代理和被代理實現相同的介面。代理者擁有被代理者的引用

一:介面

 1 package com.nonbank.commons.aop;
 2 /**
 3  * 介面類
 4  * @author sxf
 5  *
 6  */
 7 public interface Player {
 8     /**
 9      *打怪升級
10      */
11     public void killBoss();
12 }
View Code

二:被代理者

 1 package com.nonbank.commons.aop;
 2 /**
 3  * 真實玩家
 4  * @author sxf
 5  *
 6  */
 7 public class GamePlayer implements Player{
 8 
 9     @Override
10     public void killBoss() {
11         System.out.println("GamePlayer.killBoss()=======>打死一個boss");
12     }
13     
14     
15 
16 }
View Code

三:代理者

 1 package com.nonbank.commons.aop;
 2 
 3 import org.drools.rule.builder.dialect.java.parser.JavaParser.parExpression_return;
 4 
 5 /**
 6  * 代理玩家
 7  * @author sxf
 8  *
 9  */
10 public class GamePlayer_Poxy implements Player {
11     
12     
13     
14     /**
15      * 被代理的玩家
16      */
17     private Player player;
18     
19     
20      public GamePlayer_Poxy() {
21         
22     }
23      
24      public GamePlayer_Poxy(GamePlayer player) {
25         this.player=player;
26     }
27     
28     @Override
29     public void killBoss() {
30         System.out.println("GamePlayer_Poxy.killBoss()===>代理實現的一些增強前");
31         player.killBoss();
32         System.out.println("GamePlayer_Poxy.killBoss()===>代理實現的一些增強後");
33         
34     }
35 
36     
37 }
View Code

四:測試類

 1 package com.nonbank.commons.aop;
 2 
 3 public class AopTest {
 4 
 5     public static void main(String[] args) {
 6         
 7     }
 8     
 9     /**
10      * 普通的靜態代理
11      */
12     public static void test01(){
13         //被代理角色
14         GamePlayer gamePlayer=new GamePlayer();
15         //代理角色
16         GamePlayer_Poxy poxy=new GamePlayer_Poxy(gamePlayer);
17         //代理角色持有被代理角色的引用,代理和被代理實現相同的介面
18         poxy.killBoss();
19     }
20     
21 }
View Code

 

(2)動態代理,代理指定介面的實現

一:介面

 1 package com.nonbank.commons.aop;
 2 /**
 3  * 動態代理,被代理的介面
 4  * @author sxf
 5  *
 6  */
 7 public interface Mlayer {
 8     /**
 9      * 打怪
10      * @param name
11      * @return
12      */
13     public String killBoss(String name);
14     /**
15      * 登陸
16      * @param name
17      * @param password
18      * @return
19      */
20     public String login(String name,String password);
21 }
View Code

二:動態代理執行器,也就是在此處新增增強的實現類

 1 package com.nonbank.commons.aop;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 /**
 6  * 動態代理的增強類,實現代理的類
 7  * @author sxf
 8  *
 9  */
10 public class MyInvocationHandler implements InvocationHandler{
11     /**
12      * 被代理的真實物件
13      */
14     private Object target;
15     
16     
17     
18     public MyInvocationHandler() {
19         
20     }
21     
22     public MyInvocationHandler(Object target){
23         this.target=target;
24     }
25 
26     @Override
27     public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
28         System.out.println("MyInvocationHandler.invoke()===>動態代理實現了一些增強前..................");
29         Object object=method.invoke(this.target, args);
30         System.out.println("MyInvocationHandler.invoke()===>動態代理實現了一些增強後..................");
31         return object;
32     }
33     
34 
35 }
View Code

三:被代理者的實現類

 1 package com.nonbank.commons.aop;
 2 /**
 3  * 動態代理被代理者
 4  * @author sxf
 5  *
 6  */
 7 public class SxfGamePlayer  implements Mlayer{
 8 
 9     
10     @Override
11     public String killBoss(String name){
12         System.out.println("SxfGamePlayer.killBoss()要打的怪物名字是===>"+name);
13         return name+"這個怪物被打死了";
14     }
15 
16     @Override
17     public String login(String name, String password) {
18         System.out.println("SxfGamePlayer.login()登陸的名字是===>name=["+name+"]password=["+password+"]");
19         return "sxf你登陸成功了";
20     }
21     
22     
23 
24     
25 }
View Code

四:測試類

 1 package com.nonbank.commons.aop;
 2 
 3 import java.lang.reflect.Proxy;
 4 
 5 public class AopTest {
 6 
 7     public static void main(String[] args) {
 8         test02();
 9     }
10     
11     /**
12      * 普通的靜態代理
13      */
14     public static void test01(){
15         //被代理角色
16         GamePlayer gamePlayer=new GamePlayer();
17         //代理角色
18         GamePlayer_Poxy poxy=new GamePlayer_Poxy(gamePlayer);
19         //代理角色持有被代理角色的引用,代理和被代理實現相同的介面
20         poxy.killBoss();
21     }
22     
23     /**
24      * 動態代理測試
25      */
26     public static void test02(){
27         //被代理物件的真實角色
28         SxfGamePlayer paGamePlayer=new SxfGamePlayer();
29         //生成代理執行的Handler
30         MyInvocationHandler myInvocationHandler=new MyInvocationHandler(paGamePlayer);
31         //獲取當前執行緒的類載入器
32         ClassLoader classLoader=paGamePlayer.getClass().getClassLoader();
33         //動態生成代理物件(當前執行緒的類載入器,當前被代理物件的所有介面,生成的代理執行的Handler)
34         Mlayer mylMlayer=(Mlayer) Proxy.newProxyInstance(paGamePlayer.getClass().getClassLoader(),paGamePlayer.getClass().getInterfaces(), myInvocationHandler);
35         //執行被代理的方法
36         String result=mylMlayer.killBoss("王者榮耀之暴君");
37         System.out.println("AopTest.test02()killBoss執行結果==>"+result);
38         
39         String resultSt=mylMlayer.login("王者孫悟空", "12345");
40         System.out.println("AopTest.test02()login執行結果===>"+resultSt);
41         
42         /**
43          * MyInvocationHandler.invoke()===>動態代理實現了一些增強前..................
44             SxfGamePlayer.killBoss()要打的怪物名字是===>王者榮耀之暴君
45             MyInvocationHandler.invoke()===>動態代理實現了一些增強後..................
46             AopTest.test02()killBoss執行結果==>王者榮耀之暴君這個怪物被打死了
47             MyInvocationHandler.invoke()===>動態代理實現了一些增強前..................
48             SxfGamePlayer.login()登陸的名字是===>name=[王者孫悟空]password=[12345]
49             MyInvocationHandler.invoke()===>動態代理實現了一些增強後..................
50             AopTest.test02()login執行結果===>sxf你登陸成功了
51         *
52          */
53     }
54 }
View Code

 

擴充套件:對生成的代理類進行再次代理

再次代理的增強

 1 package com.nonbank.commons.aop;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 /**
 6  * 對第一層代理類進行第二次代理
 7  * @author sxf
 8  *
 9  */
10 public class MyInvocationHandler2 implements InvocationHandler{
11     
12     private Object object;
13     
14     public MyInvocationHandler2(Object object){
15         this.object=object;
16     }
17 
18     @Override
19     public Object invoke(Object proxy, Method method, Object[] args)
20             throws Throwable {
21         System.out.println("MyInvocationHandler2.invoke()sxfffffffffffffffffffffffffffffffstart");
22         Object objectd=method.invoke(this.object,args);
23         System.out.println("MyInvocationHandler2.enclosing_method()sxffffffffffffffffffffend");
24         
25         return objectd;
26     }
27 
28     
29     
30 }
View Code

再次代理的實現

 1 package com.nonbank.commons.aop;
 2 
 3 import java.lang.reflect.Proxy;
 4 import java.sql.Connection;
 5 import java.sql.DriverManager;
 6 import java.sql.SQLException;
 7 
 8 public class AopTest {
 9 
10     public static void main(String[] args) {
11         test02();
12     }
13     
14     /**
15      * 普通的靜態代理
16      */
17     public static void test01(){
18         //被代理角色
19         GamePlayer gamePlayer=new GamePlayer();
20         //代理角色
21         GamePlayer_Poxy poxy=new GamePlayer_Poxy(gamePlayer);
22         //代理角色持有被代理角色的引用,代理和被代理實現相同的介面
23         poxy.killBoss();
24     }
25     
26     /**
27      * 動態代理測試
28      */
29     public static void test02(){
30         //被代理物件的真實角色
31         SxfGamePlayer paGamePlayer=new SxfGamePlayer();
32         //生成代理執行的Handler
33         MyInvocationHandler myInvocationHandler=new MyInvocationHandler(paGamePlayer);
34         //獲取當前執行緒的類載入器
35         ClassLoader classLoader=paGamePlayer.getClass().getClassLoader();
36         //動態生成代理物件(當前執行緒的類載入器,當前被代理物件的所有介面,生成的代理執行的Handler)
37         Mlayer mylMlayer=(Mlayer) Proxy.newProxyInstance(paGamePlayer.getClass().getClassLoader(),paGamePlayer.getClass().getInterfaces(), myInvocationHandler);
38     
39         MyInvocationHandler2 myInvocationHandler2=new MyInvocationHandler2(mylMlayer);
40         Mlayer mylMlayer2=(Mlayer) Proxy.newProxyInstance(paGamePlayer.getClass().getClassLoader(),paGamePlayer.getClass().getInterfaces(), myInvocationHandler2);
41         //執行被代理的方法
42         String result=mylMlayer2.killBoss("王者榮耀之暴君");
43         System.out.println("AopTest.test02()killBoss執行結果==>"+result);
44         
45         String resultSt=mylMlayer2.login("王者孫悟空", "12345");
46         System.out.println("AopTest.test02()login執行結果===>"+resultSt);
47         
48         /**
49          * MyInvocationHandler2.invoke()sxfffffffffffffffffffffffffffffffstart
50             MyInvocationHandler.invoke()===>動態代理實現了一些增強前..................
51             SxfGamePlayer.killBoss()要打的怪物名字是===>王者榮耀之暴君
52             MyInvocationHandler.invoke()===>動態代理實現了一些增強後..................
53             MyInvocationHandler2.enclosing_method()sxffffffffffffffffffffend
54             AopTest.test02()killBoss執行結果==>王者榮耀之暴君這個怪物被打死了
55             MyInvocationHandler2.invoke()sxfffffffffffffffffffffffffffffffstart
56             MyInvocationHandler.invoke()===>動態代理實現了一些增強前..................
57             SxfGamePlayer.login()登陸的名字是===>name=[王者孫悟空]password=[12345]
58             MyInvocationHandler.invoke()===>動態代理實現了一些增強後..................
59             MyInvocationHandler2.enclosing_method()sxffffffffffffffffffffend
60             AopTest.test02()login執行結果===>sxf你登陸成功了
61 
62         *
63          */
64     }
65     
66     
67     public static void test03() throws SQLException{
68         Connection connection= DriverManager.getConnection("連線URL", "使用者名稱", "密碼");
69         //關閉自動提交
70         connection.setAutoCommit(false);
71         //該連線所有操作進行提交提交
72         connection.commit();
73         //該連結所有操作進行回滾
74         connection.rollback();
75         //connection.rollback(savepoint);
76         //spring的事務管理器,在aop程式設計(動態代理)的增強方法中實現事務管理的編碼,可以實現提交和回滾
77         
78     }
79     
80     
81     public static void springInvoker(){
82         
83     }
84 }
View Code

 

 

 

 

三:spring的事務管理,就是基於動態代理aop程式設計實現事務管理,宣告式事務程式設計,編碼式事務程式設計

 1 public static void test03() throws SQLException{
 2         Connection connection= DriverManager.getConnection("連線URL", "使用者名稱", "密碼");
 3         //關閉自動提交
 4         connection.setAutoCommit(false);
 5         //該連線所有操作進行提交提交
 6         connection.commit();
 7         //該連結所有操作進行回滾
 8         connection.rollback();
 9         //connection.rollback(savepoint);
10         //spring的事務管理器,在aop程式設計(動態代理)的增強方法中實現事務管理的編碼,可以實現提交和回滾
11         
12     }
View Code

 

相關文章