设计模式之禅之代理模式

简介: jdk的动态代理的条件:===>要实现动态代理的首要条件是:被代理类必须实现一个接口,回想一下前面的分析吧。当然了,现在也有很多技术如CGLIB可以实现不需要接口也可以实现动态代理的方式。 动态代理的应用代理模式应用得非常广泛,大到一个系统框架、企业平台,小到代码片段、事务处理,稍不留意就用到代理模式。

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

 

相关文章
|
7月前
|
设计模式 缓存 监控
【设计模式系列笔记】代理模式
代理模式是一种结构型设计模式,它允许一个对象(代理对象)控制另一个对象的访问。代理对象通常充当客户端和实际对象之间的中介,用于对实际对象的访问进行控制、监控或其他目的。
127 1
|
7月前
|
设计模式 缓存 安全
小谈设计模式(8)—代理模式
小谈设计模式(8)—代理模式
|
3月前
|
设计模式 缓存 安全
设计模式——代理模式
静态代理、JDK动态代理、Cglib 代理
设计模式——代理模式
|
7月前
|
设计模式 Java
Java一分钟之-设计模式:装饰器模式与代理模式
【5月更文挑战第17天】本文探讨了装饰器模式和代理模式,两者都是在不改变原有对象基础上添加新功能。装饰器模式用于动态扩展对象功能,但过度使用可能导致类数量过多;代理模式用于控制对象访问,可能引入额外性能开销。文中通过 Java 代码示例展示了两种模式的实现。理解并恰当运用这些模式能提升代码的可扩展性和可维护性。
69 1
|
3月前
|
设计模式 Java 数据安全/隐私保护
Java设计模式-代理模式(7)
Java设计模式-代理模式(7)
|
7月前
|
设计模式 Java 数据库连接
【重温设计模式】代理模式及其Java示例
【重温设计模式】代理模式及其Java示例
|
4月前
|
设计模式 缓存 Java
【十一】设计模式~~~结构型模式~~~代理模式(Java)
文章详细介绍了代理模式(Proxy Pattern),这是一种对象结构型模式,用于给对象提供一个代理以控制对它的访问。文中阐述了代理模式的动机、定义、结构、优点、缺点和适用环境,并探讨了远程代理、虚拟代理、保护代理等不同代理形式。通过一个商务信息查询系统的实例,展示了如何使用代理模式来增加身份验证和日志记录功能,同时保持客户端代码的无差别对待。此外,还讨论了代理模式在分布式技术和Spring AOP中的应用,以及动态代理的概念。
【十一】设计模式~~~结构型模式~~~代理模式(Java)
|
4月前
|
设计模式
设计模式的基础问题之代理模式在工作中的问题如何解决
设计模式的基础问题之代理模式在工作中的问题如何解决
|
5月前
|
设计模式 算法 Go
iLogtail设计模式问题之代理模式在iLogtail中是如何应用的
iLogtail设计模式问题之代理模式在iLogtail中是如何应用的
|
5月前
|
设计模式 缓存 JavaScript
js设计模式【详解】—— 代理模式
js设计模式【详解】—— 代理模式
33 0