什么是代理模式

代理模式就是为一个对象提供一个代理对象,由这个代理对象控制对该对象的访问。

理解代理模式,可以对照生活中的一些具体例子,比如房产中介、二手车交易市场、经纪人等。

为什么要用代理模式

通过使用代理模式,我们避免了直接访问目标对象时可能带来的一些问题,比如:远程调用,需要使用远程代理来帮我们处理一些网络传输相关的细节逻辑;可能需要基于某种权限控制对目标资源的访问,可以使用保护代理等。

总的来说,通过是用代理模式,我们可以控制对目标对象的访问,可以在真实方法被调用前或调用后,通过代理对象加入额外的处理逻辑。

代理模式分类

代理模式分为静态代理和动态代理。动态代理根据实现不同又可细分为JDK动态代理和cglib动态代理。

静态代理是由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。

动态代理是在实现阶段不用关心代理类,而在运行时动态生成代理类的。

静态代理

以房哥买房子为例,用代码实现静态代理。

1、首先建立一个Seller接口

public interface Seller {     void sell(); }

2、创建实现类,房哥,有一个方法,就是买房子

public class FangGe implements Seller{     @Override     public void sell() {         System.out.println("房哥要出手一套四合院");     } }

3、买房子需要找到买家,达成交易后还要办理过户等其他手续,房哥只想卖房收钱就完了。因此,需要找一个代理来帮房哥处理这些杂事。

我们创建一个代理类FangGeProxy,代理类也需要实现Seller接口,行为上要保持和FangGe一样,都是要卖房子。同时该代理类还需要持有房哥的引用。

public class FangGeProxy implements Seller{     private FangGe fangGe;      public FangGeProxy(FangGe fangGe){         this.fangGe = fangGe;     }     @Override     public void sell() {         findBuyer();         fangGe.sell();         afterSell();     }          public void findBuyer(){         System.out.println("代理帮助寻找买主");     }          public void afterSell(){         System.out.println("达成交易后,办理相关手续");     } }

可以看到,房哥的代理类通过findBuyer()和afterSell()两个方法帮助房哥完成了其他一些杂事。

4、测试类

public class StaticProxyTest {     public static void main(String[] args) {         Seller seller = new FangGeProxy(new FangGe());         seller.sell();     } }

输出:

代理帮助寻找买主 房哥要出手一套四合院 达成交易后,办理相关手续

最后,看下类图
在这里插入图片描述

静态代理的问题:

1、由于静态代理类在编译前已经确定了代理的对象,因此静态代理只能代理一种类型的类,如果要给大量的类做代理,就需要编写大量的代理类;

2、如果我们要给Seller,也就是目标对象要增加一些方法,则需要同步修改代理类,不符合开闭原则。

JDK动态代理

JDK的动态代理依赖于jdk给我们提供的类库实现,是一种基于接口实现的动态代理,在编译时并不知道要代理哪个类,而是在运行时动态生成代理类。同时也解决了静态代理中存在的问题。

我们接上上面静态代理的例子,继续实现JDK的动态代理。

1、我们建一个方法转发的处理器类,该类需要实现InvocationHandler接口。

public