动态代理模式
来源:互联网 发布:vip域名交易 编辑:程序博客网 时间:2024/06/08 01:30
什么是动态代理
动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。相对来说,自己写代理类的方式就是静态代理。
现在有一个非常流行的名称叫做面向切面编程,也就是AOP(Aspect Oriented Programming)其核心就是采用了动态代理机制。
动态代理模式简单类图
(以gameplay为例)
上图中InvocationHandle接口和GamePlayIH类 作用就是产生一个对象的代理对象,其中InvocationHandle是JDK提供的动态代理接口,对被代理类的方法进行代理
GamePlayIH类代码如下
package dynamicproxypatern;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class GamePlayIH implements InvocationHandler { //被代理的实例 Object obj = null; //我要代理谁 public GamePlayIH(Object _obj) { this.obj = _obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub Object result = method.invoke(this.obj, args); return result; }}
其中invoke方法是InvocationHandler接口中定义必须实现的,它完成对真实方法的调用。
InvocationHandler接口介绍,动态代理根据被代理的接口生成所有的方法,只是所有的方法都是空的,通过InvocationHandler接口,把所有的方法交由该Handle处理。即所有被代理的方法都有InvocationHandler接管实际的处理任务。
抽象主题角色(游戏玩家接口)代码如下
package dynamicproxypatern;public interface IGamePlayer { public void login(String user,String password); public void killBoss(); public void upgrade();}
具体主题角色(具体玩家类)代码如下
package dynamicproxypatern;public class GamePlayer implements IGamePlayer { private String name = ""; public GamePlayer(String _name) { this.name = _name; } @Override public void login(String user, String password) { // TODO Auto-generated method stub System.out.println("登录名为" + user + "的用户 " + this.name + "登录成功!"); } @Override public void killBoss() { // TODO Auto-generated method stub System.out.println(this.name + "在打怪!"); } @Override public void upgrade() { // TODO Auto-generated method stub System.out.println(this.name + "又升了一级!"); }}
客户端测试类
package dynamicproxypatern;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;import java.time.LocalDateTime;public class Client { public static void main(String[] args) { // TODO Auto-generated method stub IGamePlayer player = new GamePlayer("张三"); InvocationHandler handler = new GamePlayIH(player); System.out.println("开始时间是:" + LocalDateTime.now()); ClassLoader cl = player.getClass().getClassLoader(); IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl, new Class[] {IGamePlayer.class}, handler); proxy.login("zhangsan", "password"); proxy.killBoss(); proxy.upgrade(); System.out.println("结束时间是:" + LocalDateTime.now()); }}
输出结果为
开始时间是:2017-09-29T15:52:15.356
登录名为zhangsan的用户 张三登录成功!
张三在打怪!
张三又升了一级!
结束时间是:2017-09-29T15:52:15.360
客户端测试类另一种写法
import java.time.LocalDateTime;public class Client { public static void main(String[] args) { // TODO Auto-generated method stub IGamePlayer player = new GamePlayer("张三"); InvocationHandler handler = new GamePlayIH(player); System.out.println("开始时间是:" + LocalDateTime.now()); Class c = player.getClass(); IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(c.getClassLoader(), c.getInterfaces(), handler); proxy.login("zhangsan", "password"); proxy.killBoss(); proxy.upgrade(); System.out.println("结束时间是:" + LocalDateTime.now()); }}
如何在游戏登录后发送消息?
修改下代理类,是代理类的方法代理为login方法时,处理一些事情
package dynamicproxypatern;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class GamePlayIH implements InvocationHandler { //被代理的实例 Object obj = null; //我要代理谁 public GamePlayIH(Object _obj) { this.obj = _obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub Object result = method.invoke(this.obj, args); if(method.getName().equals("login")) { System.out.println("登录时发送一些消息"); } return result; }}
其他的类都不用动,输出结果为
开始时间是:2017-09-29T15:59:50.307
登录名为zhangsan的用户 张三登录成功!
登录时发送一些消息
张三在打怪!
张三又升了一级!
结束时间是:2017-09-29T15:59:50.311
以上的发送消息就是AOP编程,使得我们在设计系统时不用考虑日志、事务、权限等等,而是在设计以后用AOP的方式切过去。
动态代理通用形式和代码
动态代理的通用类图如下(重点)
由上图可以看出两条独立发展的线路,动态代理实现代理的职责,subject实现相关的逻辑功能,advice(通知)从另一个切面切入,然后在高层模块也就是client进行耦合。
代码展示
抽象主题类
package dynamicproxypatern;public interface Subject { //业务操作 public void doSomething(String str);}
具体主题类
package dynamicproxypatern;public class RealSubject implements Subject { @Override public void doSomething(String str) { // TODO Auto-generated method stub System.out.println("do something --->" + str); }}
通知接口
package dynamicproxypatern;public interface IAdvice { public void exec();}
前置通知类
package dynamicproxypatern;public class BeforeAdvice implements IAdvice { @Override public void exec() { // TODO Auto-generated method stub System.out.println("我是前置通知,先执行了我"); }}
动态代理的Handle类
package dynamicproxypatern;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler { //被代理的对象 Object obj = null; //我要代理谁 public MyInvocationHandler(Object _obj) { this.obj = _obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub return method.invoke(this.obj, args); }}
动态代理类
package dynamicproxypatern;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class DynamicProxy<T> { public static <T> T newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) { if(true) { (new BeforeAdvice()).exec(); } return (T) Proxy.newProxyInstance(loader, interfaces, h); }}
客户端测试类
package dynamicproxypatern;import java.lang.reflect.InvocationHandler;import java.time.LocalDateTime;public class Client { public static void main(String[] args) { // TODO Auto-generated method stub Subject subject = new RealSubject(); InvocationHandler handler = new MyInvocationHandler(subject); Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler); System.out.println("开始时间是:" + LocalDateTime.now()); proxy.doSomething("测试一下"); System.out.println("结束时间是:" + LocalDateTime.now()); }}
输出结果为
我是前置通知,先执行了我
开始时间是:2017-09-29T16:42:45.985
do something —>测试一下
结束时间是:2017-09-29T16:42:45.986
- 代理模式--动态代理
- 代理模式 & 动态代理
- 代理模式--动态代理
- 代理模式(动态代理)
- 代理模式-动态代理
- 代理模式-动态代理
- 代理模式动态代理
- 代理模式-动态代理
- 代理模式 -动态代理
- 代理模式---动态代理
- 代理模式-动态代理
- 代理模式之动态代理
- java代理模式--动态代理
- 代理模式之动态代理
- 代理模式之动态代理
- 代理模式之动态代理
- 代理模式和动态代理
- 代理模式与动态代理
- 翻译连载 | 第 10 章:异步的函数式(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
- android permission权限与安全机制解析(下)
- Hibrenate入门实例
- Spring-boot:5分钟整合Dubbo构建分布式服务
- java中String、StringBuffer、StringBuilder的区别
- 动态代理模式
- 打开MySQL数据库远程访问的权限
- 移动端touch事件实现页面弹动--小插件
- 微信小程序弹出框详解
- Framework学习(一)Android 系统架构
- android studio集成ijkplayer
- 阿里云ECS ubuntu 14.04 搭建svn以及使用实践记录
- wpf仿163收件人
- iOS开发中属性 property 和 synthesize