設計模式之禪之代理模式
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 }
二:被代理者
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 }
三:代理者
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 }
四:測試類
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 }
(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 }
二:動態代理執行器,也就是在此處新增增強的實現類
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 }
三:被代理者的實現類
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 }
四:測試類
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 }
擴充套件:對生成的代理類進行再次代理
再次代理的增強
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 }
再次代理的實現
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 }
三: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 }
相關文章
- 玩轉設計模式——設計模式之禪2010-02-25設計模式
- 《設計模式》之代理模式2019-02-17設計模式
- 【設計模式之代理模式】2016-03-06設計模式
- 設計模式之代理模式2024-05-13設計模式
- Javascript設計模式之代理模式2019-04-08JavaScript設計模式
- Java設計模式之代理模式2020-11-14Java設計模式
- 設計模式系列之「代理模式」2017-12-02設計模式
- 設計模式之代理2021-08-18設計模式
- Java設計模式-之代理模式(動態代理)2017-09-10Java設計模式
- 設計模式之代理模式(proxy pattern)2019-05-31設計模式
- 23天設計模式之代理模式2021-06-20設計模式
- Java設計模式之(五)——代理模式2021-11-22Java設計模式
- C++設計模式之代理模式2018-04-14C++設計模式
- 設計模式漫談之代理模式2018-04-22設計模式
- Java設計模式之代理模式(Proxy)2016-07-22Java設計模式
- 我學設計模式 之 代理模式2010-09-22設計模式
- 讀秦小波《設計模式之禪》 -- 單例模式2015-01-01設計模式單例
- 讀秦小波《設計模式之禪》 -- 工廠模式2014-12-25設計模式
- C++設計模式之Proxy模式(代理模式)2019-07-26C++設計模式
- 23種設計模式之代理模式(靜態代理)2020-07-19設計模式
- JavaScript設計模式經典之代理模式2021-09-09JavaScript設計模式
- 設計模式之代理模式(結構型)2019-01-19設計模式
- 12.java設計模式之代理模式2020-11-20Java設計模式
- JAVA設計模式之 代理模式【Proxy Pattern】2015-01-10Java設計模式
- C#設計模式之代理模式(四)2012-11-27C#設計模式
- C#設計模式之代理模式(三)2012-11-27C#設計模式
- C#設計模式之代理模式(二)2012-11-26C#設計模式
- C#設計模式之代理模式(一)2012-11-26C#設計模式
- 設計模式之觀察和代理2018-12-18設計模式
- 23種設計模式之——動態代理模式2021-01-04設計模式
- javascript設計模式 之 3代理模式2018-05-30JavaScript設計模式
- 跟著GPT學設計模式之代理模式2024-03-02GPT設計模式
- Java設計模式之七 —– 享元模式和代理模式2019-01-23Java設計模式
- android常用設計模式之代理設計模式及動態代理原理2018-01-09Android設計模式
- 設計模式(十六)----結構型模式之代理享元模式2023-03-06設計模式
- 設計模式之cglib動態代理2024-08-20設計模式CGLib
- Java進階篇設計模式之七 —– 享元模式和代理模式2019-03-04Java設計模式
- Java進階篇設計模式之七 ----- 享元模式和代理模式2018-09-25Java設計模式