一. 代理模式
代理模式作为23种经典设计模式之一,其比较官方的定义为“为其他对象提供一种代理以控制对这个对象的访问”,简单点说就是,之前A类自己做一件事,在使用代理之后,A类不直接去做,而是由A类的代理类B来去做。代理类其实是在之前类的基础上做了一层封装。java中有静态代理、JDK动态代理、CGLib动态代理的方式。静态代理指的是代理类是在编译期就存在的,相反动态代理则是在程序运行期动态生成的
二. 静态代理
1. 案例
-
接口
public interface Rent { public void rent(); }
-
实现类
public class Host implements Rent { public void rent() { System.out.println("房东出租房子"); } }
-
代理类
public class Proxy { private Host host; public Proxy(){ } public Proxy(Host host) { this.host = host; } public void rent(){ System.out.println("代理操作,开启事务"); host.rent(); System.out.println("代理操作,关闭事务"); } }
-
测试
public class Client { // 不使用代理 @Test public void test01(){ Host host = new Host(); host.rent(); } // 通过代理调用 @Test public void test02(){ Host host = new Host(); // 代理 Proxy proxy = new Proxy(host); proxy.rent(); } }
2. 说明:
- 对比,使用静态代理和不使用静态代理,可以发现使用了代理之后,可以在被代理方法的执行前或后加入别的代码,实现诸如权限及日志的操作。
- 静态代理也存在一定的问题,如果被代理方法很多,就要为每个方法进行代理,增加了代码维护的成本。有没有其他的方式可以减少代码的维护,那就是动态代理。
三. JDK动态代理
1. 案例
-
接口
public interface Rent { public void rent(); }
-
实现类
public class Host implements Rent { public void rent() { System.out.println("房东出租房子"); } }
-
动态代理类
// 动态生成代理类 public class ProxyInvocationHandler implements InvocationHandler { // 被代理的接口 private Rent rent; public void setRent(Rent rent) { this.rent = rent; } // 生成得到代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this); } // 处理代理实例, 并返回代理结果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 动态代理的本质: 就是使用反射机制实现 seeHouse(); Object result = method.invoke(rent, args); fare(); return result; } public void seeHouse() { System.out.println("中介带着看房"); } public void fare(){ System.out.println("中介收取中介费"); } }
-
测试
public class Client { @Test public void test01(){ // 真实角色 Host host = new Host(); // 代理角色, 现在没有 ProxyInvocationHandler handler = new ProxyInvocationHandler(); // 通过调用程序处理角色来处理我们要调用的接口对象 handler.setRent(host); Rent proxy = (Rent) handler.getProxy(); proxy.rent(); } }