Java设计模式之代理模式
来源:互联网 发布:thinkphp5 nginx配置 编辑:程序博客网 时间:2024/06/13 07:45
代理模式
代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象时,客户端实际上不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就可返回该对象的代理(Proxy)。
代理就是一个Java对象代表另一个Java对象来采取行动。如:
静态代理模式:
public interface Image { public void show();}
package com.mystudy.designPattern.proxy;public class BigImage implements Image { public void show() { System.out.println("这是BigImage"); }}
package com.mystudy.designPattern.proxy;/** * hibernate默认启用延迟加载,当系统加载A实体时,A实体关联的B实体并未被加载出来, * A实体所关联的B实体全部是代理对象——只有等到A实体真正需要访问B实体时, 系统才会去数据库里抓取B实体所对应的记录。 */public class ImageProxy implements Image { // 组合一个image实例,作为被代理的对象 // //真实对象的引用 private Image image; public ImageProxy(Image image) { this.image = image; } /** *重写Image接口的show()方法, 该方法用于控制对被代理对象的访问, 并根据需要负责创建和删除被代理对象 */ public void show() { // 只有当真正需要调用image的show方法时才创建被代理对象 if (image == null) { image = new BigImage(); } image.show(); }}
静态代理模式测试代码:
package com.mystudy.designPattern.proxy;public class ImageProxyTest { public static void main(String[] args) { Image bigImage = new BigImage(); Image imageProxy = new ImageProxy(bigImage); imageProxy.show(); }}
测试结果:
代理模式的应用:
hibernate默认启用延迟加载,当系统加载A实体时,A实体关联的B实体并未被加载出来,A实体所关联的B实体全部是代理对象——只有等到A实体真正需要访问B实体时,系统才会去数据库里抓取B实体所对应的记录。
借助于Java提供的Proxy和InvocationHandler,可以实现在运行时生成动态代理的功能,而动态代理对象就可以作为目标对象使用,而且增强了目标对象的功能。在代理对象前后就可以添加我们自己的操作。如:
package com.mystudy.designPattern.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class ImageInvokationHandler implements InvocationHandler { private Image bigImage; public void setTarget(Image bigImage) { this.bigImage = bigImage; } /** * 动态代理类$Proxy0调用xiangQin方法时会调用它自己的xiangQin方法, * 而它自己的xiangQin方法里面调用的是super.h.invoke(this, , ),也就是父类Proxy的h的invoke方法, * 也就是ReadyInvocationHandler类的invoke方法。 所以,invoke(Object proxy, Method m, * Object[] args)种的proxy实际上就是动态代理类$Proxy0, * 如果你将其强转成XiangQinInterface然后调用它的xiangQin方法,然后它就会调用super.h.invoke(this, , * ),这样就会死循环。 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { TxUtil txUtil = new TxUtil(); txUtil.beginTx(); Object result = method.invoke(bigImage, args); txUtil.endTx(); return result; }}
在代理对象前后就可以添加我们自己的操作:
package com.mystudy.designPattern.proxy;public class TxUtil { public void beginTx() { System.out.println("===模拟业事务开始"); } public void endTx() { System.out.println("===模拟事务结束"); }}
测试代码:
package com.mystudy.designPattern.proxy;import java.lang.reflect.Proxy;public class ImageInvokationHandlerTest { public static void main(String[] args) { // 先将BigImage实现类实例化,也就是得到Image接口的一个实例对象 Image bigImage = new BigImage(); /** * 得到BigImage这个类的一个代理类,同时为代理类绑定了一个处理类ImageInvokationHandler。 * 听着很绕口,其实就是每次调用bigImage这个子类的show()方法时, 不是Image这个BigImage类的实例去调用, * 而是这个bigImage的代理类ImageInvokationHandler去调用它自己的invoke方法, * 这个invoke方法里呢可以调用bigImage这个实例的show()方法 */ /** * 在java种怎样实现动态代理呢 第一步,我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象, * 所谓代理呢也就是在调用实现类的方法时,可以在方法执行前后做额外的工作,这个就是代理。 * 第二步,我们要自己写一个在要代理类的方法执行时,能够做额外工作的类,而这个类必须继承InvocationHandler接口, * 为什么要继承它呢?因为代理类的实例在调用实现类的方法的时候,不会调真正的实现类的这个方法, * 而是转而调用这个类的invoke方法(继承时必须实现的方法),在这个方法中你可以调用真正的实现类的这个方法。 * 第三步,在要用代理类的实例去调用实现类的方法的时候,写出下面两段代码。 */ ImageInvokationHandler handler = new ImageInvokationHandler(); handler.setTarget(bigImage); Image image = (Image) Proxy .newProxyInstance(bigImage.getClass().getClassLoader(), bigImage.getClass().getInterfaces(), handler); image.show(); /** * 这里要解释下中部那段长长的代码的意思,以及具体做了哪些工作? * 第一,根据bigImage.getClass().getClassLoader()这个要代理类的类加载器和 * bigImage.getClass().getInterfaces()要代理类所实现的所有的接口 * 作为参数调用Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces) * 的方法返回代理类的java.lang.Class对象,也就是得到了java动态生成的代理类$Proxy0的Class对象。 * 同时,java还让这个动态生成的$Proxy0类实现了要代理类的实现的所有接口,并继承了Proxy接口。 * 第二,实例化这个动态生成的$Proxy0类的一个实例,实例化代理类的构造函数为Proxy(InvocationHandler h), * 也就是说要实例化这个动态生成的$Proxy0类,必须给它一个InvocationHandler参数,也就是我们自己实现的用来在代理类 * 方法执行前后做额外工作的类ReadyInvocationHandler。 * 这段代码Proxy.newProxyInstance(bigImage * .getClass().getClassLoader(),bigImage * .getClass().getInterfaces(),handler) 得到的其实是一个类名叫$Proxy0 extends Proxy * implements Image的类。 第三,将这个$Proxy0类强制转型成Image类型,调用show()方法。 */ }}
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制。
另外一片关于代理模式的介绍也很详细,可作参考:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
阅读全文
0 0
- Java设计模式之代理设计模式
- Java设计模式之代理
- Java设计模式之代理
- java设计模式之代理
- java之代理设计模式
- java之代理设计模式
- Java设计模式之代理模式
- Java设计模式之计数代理模式
- JAVA设计模式之代理模式
- JAVA设计模式之代理模式
- java设计模式之代理模式
- Java 设计模式 之 代理模式
- java设计模式之代理模式Proxy
- 设计模式之代理模式 java (1)
- java设计模式之代理模式
- java设计模式之静态代理模式
- Java:设计模式之代理模式Proxy
- java设计模式之代理模式
- python,scrapy爬虫sql之爬取数据存储到mysql的piplelines.py配置
- 如何在AS上运行Github里面的代码
- python 装饰器
- flex-layout
- easyui综合布局demo
- Java设计模式之代理模式
- Java代码操作Redis
- bzoj 2748: [HAOI2012]音量调节 dp
- 兴业银行总行信息科技部笔试+面试经验
- QEMU动态翻译器
- MySQL ZIP Archive 5.7.17 安装方法
- 静态广播实现app自启动
- 一个*号引发的事故
- sql server存储过程