设计模式之禅之代理模式
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 }