博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
后台(29)——动态代理
阅读量:6851 次
发布时间:2019-06-26

本文共 4028 字,大约阅读时间需要 13 分钟。




本文已经deprecated,关于动态代理,请参见


版权声明

  • 本文原创作者:
  • 作者博客地址:

代理模式简介

代理模式(Proxy Pattern)是面向对象中一种非常常见的设计模式。其实,不单是在软件开发领域,在我们的日常生活中对于代理也时常可见。比如:房东要将自家的房租出售,于是到房地产中介公司找一个代理,由他来帮自己完成销售房屋,签订合同等等事宜。

在此,就以该生活场景为蓝本介绍Java的代理模式。


静态代理

房东通过一纸协议将自己的房子挂靠在房屋中介;嗯哼,我们来一起瞅瞅这个房东和中介公司共同达成的协议:

/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;public interface TradeProtocol {
public void sellHouse(int money);}

嗯哼,这个协议很简单,房东委托中介公司售卖自己的房子。

既然是房东和房屋中介共同达成的协议,那么房东和中介都需要遵守该协议。

先来看房东:

/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;public class Owner implements TradeProtocol{
@Override public void sellHouse(int money) { System.out.println("我是房主,我的房子卖了"+money+"块钱"); }}

再来看中介:

/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;public class HouseAgent implements TradeProtocol {
private TradeProtocol mHouseProtocol; public HouseAgent(TradeProtocol houseProtocol){ mHouseProtocol=houseProtocol; } @Override public void sellHouse(int money) { System.out.println("我是中介,业主的房子卖了"+money+"块钱"); mHouseProtocol.sellHouse(money); }}

请注意HouseAgent的实现

  • 在HouseAgent的构造方法中传入TradeProtocol的对象比如Owner
  • 在HouseAgent的sellHouse()中调用TradeProtocol的对象(比如Owner)的sellHouse()
  • 所以,HouseAgent售卖(sellHouse())房子,实际上是房东售卖了房屋

测试如下:

/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;public class Test {
public static void main(String[] args) { Owner owner=new Owner(); HouseAgent houseAgent=new HouseAgent(owner); houseAgent.sellHouse(10000*100); }}

测试结果:

我是中介,业主的房子卖了1000000块钱我是房主, 我的房子卖了 1000000块钱

在该静态代理中,房东将房屋的售卖交给了中介代理,中介将房屋出售后又把钱一分不少地交给了房东。咦,这咋不对呢?现实中有这样大公无私,视金钱如粪土的房屋中介么?没有!绝对没有!

那么,中介是怎么赚钱的呢?我们继续往下看


动态代理

与之前一样,房东和中介之间存有一纸协议:

/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;public interface TradeProtocol {
public void sellHouse(int money);}

房东遵守该协议:

/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;public class Owner implements TradeProtocol{
@Override public void sellHouse(int money) { System.out.println("我是房主,中介告诉我:房子卖了"+money+"块钱"); }}

现在,房东又去房屋中介公司挂靠自己的房子,到了那一看:原来熟悉的那个代理出去办事了,刚好不在。正准备走呢,中介公司的经理挺着啤酒肚走过来,笑嘻嘻地说:请问您是来办理业务的吗?来,请坐,我给你们引荐以为我们这里服务最好的一个房屋代理人员办理您的相关事宜

嗯哼,我们来看看这个代理是怎么卖掉房东的房子的:

/** * 本文作者:谷哥的小弟 * 博客地址:http://blog.csdn.net/lfdfhl */package cn.com;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Test {
public static void main(String[] args) { TradeProtocol owner=new Owner(); ClassLoader classLoader=owner.getClass().getClassLoader(); Class
[] interfaces = owner.getClass().getInterfaces(); TradeProtocol houseAgent=(TradeProtocol) Proxy.newProxyInstance(classLoader,interfaces, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { Object object=null; System.out.println("我是中介,业主的房子我实际卖了"+args[0]+"块钱"); object=method.invoke(owner, new Object[]{(Integer)args[0]/2}); System.out.println("我是中介,这次交易我赚了不少钱呢"); return object; } }); houseAgent.sellHouse(10000*100); }}

在该实现中由系统自动地为我们创建了一个代理Proxy.newProxyInstance()

结果如下:

我是中介,业主的房子我实际卖了1000000块钱我是房主,中介告诉我:房子卖了500000块钱我是中介,这次交易我赚了不少钱呢

哇哈,中介把房子卖了100W却告诉房东只买了50W,自己狠狠地赚了一笔!

嗯哼,这个例子我们看完了,在此对照Test类分析动态代理的实现

  • 动态代理与静态模式的原理是一样的,只是它没有具体的代理类而是通过Proxy在JVM运行时利用反射动态地生成了一个代理。
  • 请注意Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法的三个参数
    • ClassLoader:类加载器,传入和被代理类使用的相同的类加载器即可
    • Class<?>[] interface:代理类要实现的接口,传入和被代理类使用的相同的接口即可
    • InvocationHandler h:当通过代理对象调用一个方法的时候,该方法的调用会被转发至InvocationHandler接口的invoke()方法来执行具体的调用
  • 请注意invoke(Object proxy, Method method, Object[] args)方法的三个参数
    • Object proxy:代理对象的引用
    • Method method:当前调用的方法
    • Object[] args:当前调用的方法的输入参数
  • 由此可见:动态代理可方便地对委托类的方法进行某些处理,比如在方法实际调用前做一些过滤或者拦截操作,在方法调用后做一些善后处理等

后会有期

我们会在学习Spring框架时对Java动态代理机制做进一步的认识和理解

你可能感兴趣的文章
[PWA] Customize the Splash Screen of a PWA built with create-react-app
查看>>
Oracle EM错误,java.lang.Exception: Exception in sending Request :: null ...
查看>>
算法战斗:给定一个号码与通配符问号W,问号代表一个随机数字。 给定的整数,得到X,和W它具有相同的长度。 问:多少整数协议W的形式和的比率X大?...
查看>>
20140704,七月微软安全补丁的通知
查看>>
Java 多线程(2)-Executor
查看>>
解决Android中No resource found that matches android:TextAppearance.Material.Widget.Button.Inverse问题...
查看>>
【探索】在 JavaScript 中使用 C 程序
查看>>
CI框架 -- 核心文件 之 Exceptions.php
查看>>
poj 1018 Communication System
查看>>
如何通俗的理解spring的控制反转、依赖注入、面向切面编程等等
查看>>
【iOS知识学习】_iOS沙盒机制
查看>>
Java实现微信菜单json字符串拼接
查看>>
HTML设置超链接字体颜色和点击后的字体颜色
查看>>
Java后端WebSocket的Tomcat实现
查看>>
Chrome测试网站加载时间与流量消耗
查看>>
Linq-语句之存储过程
查看>>
Android开发之定义接口暴露数据
查看>>
Servlet监听器
查看>>
[LintCode] Intersection of Two Arrays II 两个数组相交之二
查看>>
【Objective-C】02-Objective-C学习及iOS开发的准备
查看>>