(1)什么是代理?
代理其实是一种软件设计模式,目的地希望能做到代码重用。具体上讲,代理这种设计模式是通过不直接访问被代理对象的方式,而访问被代理对象的方法。这个就好比 商户---->消防部门119(代理)---->消防员这种模式。我们可以不通过直接与消防对话的情况下,而通过消防119(代理)与其产生间接对话。
(2)什么情况下使用代理?
(1)设计模式中有一个设计原则是开闭原则,是说对修改关闭对扩展开放,我们在工作中有时会接手很多前人的代码,里面代码逻辑让人摸不着头脑(sometimes the code is really like shit),这时就很难去下手修改代码,那么这时我们就可以通过代理对类进行增强。
(2)我们在使用RPC框架的时候,框架本身并不能提前知道各个业务方要调用哪些接口的哪些方法 。那么这个时候,就可用通过动态代理的方式来建立一个中间人给客户端使用,也方便框架进行搭建逻辑,某种程度上也是客户端代码和框架松耦合的一种表现。
(3)Spring的AOP机制就是采用动态代理的机制来实现切面编程。
(3)静态代理和动态代理
我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理。如果我们在代码编译时就确定了被代理的类是哪一个,那么就可以直接使用静态代理;如果不能确定,那么可以使用类的动态加载机制,在代码运行期间加载被代理的类这就是动态代理,比如RPC框架和Spring AOP机制。
(4)具体实现
接口实现方式使用到jdk封装的接口和类。我们自己定义的类中使用时必须要有接口和实现类,并且实现InvocationHandler接口和Proxy类。
InvocationHandler接口
此接口有个抽象方法,
Object invoke(Object var1, Method var2, Object[] var3) throws Throwable;
var1:第一个参数是Object类型,是真实的实现类对象;
var2:第二参数是Method类型,代表调用的方法;
var3:第三个参数是Object类型,代表的是调用方法的参数;
此接口返回值是Object类型,表示真实对象的方法被调用后的返回值。
Proxy类
此类有多个方法,在这里使用到的是newProxyInstance方法。
public static Object newProxyInstance(ClassLoader var0, Class<?>[] var1, InvocationHandler var2) throws IllegalArgumentException {
var0:一个ClassLoader 对象,定义了由哪个ClassLoader对象对生成的代理对象进行加载;
var1:一个接口对象的数组,表示将需要代理的对象提供一组什么的接口,一个类可以实现多个接口,相当于实现了多态;
var2:一个InvocationHandler对象,表示动态代理调用方法时,关联到具体的InvocationHandler对象。
简单例子(1)如下:
简单例子(2)如下:
接口类:
实现类:
代理类:
测试类