全部博文(695)
分类: Java
2017-05-17 22:43:09
在静态代理中,代理Proxy中的方法,都指定了调用了特定的realSubject中的对应的方法:
在上面的静态代理模式下,Proxy所做的事情,无非是调用在不同的request时,调用触发realSubject对应的方法;更抽象点看,Proxy所作的事情;在Java中 方法(Method)也是作为一个对象来看待了,
动态代理工作的基本模式就是将自己的方法功能的实现交给 InvocationHandler角色,外界对Proxy角色中的每一个方法的调用,Proxy角色都会交给InvocationHandler来处理,而InvocationHandler则调用具体对象角色的方法。如下图所示:
在这种模式中,代理类Proxy和RealSubject都应该实现相同的功能,这里的功能可以理解为某个public方法
在面向对象的编程中,想让Proxy和RealSubject都实现相同的功能有两种方式:
a、一个比较直观的方式,就是定义一个功能接口,然后让Proxy和RealSubject都实现这个接口
b、比价隐晦的方式是通过继承。因为如果Proxy继承自RealSubject,这样Proxy则拥有了RealSubject的功能,Proxy还可通过重写RealSubject中方法来实现多态
时下比较流行的两种动态代理:JDK动态代理是以a思路设计,CGlib是以b思路设计的
JDK动态代理会做如下工作:1、获取RealSubject上所有接口,2、确定要生成的代理类的类名,默认为com.sun.proxy.$PrxoyXXX,3、根据需要实现的接口信息在代码中动态创建该Proxy类的字节码(byte[] classFile = ProxyGenerator.generateProxyClass(proxyName, clazz.getInterfaces());),4、将字节码转换成对应的class对象(所以需要传入classloader做参数),5、创建InvocationHandler实例对象,用来处理Proxy所有方法的调用,6、Prxoy的class对象以创建的handler对象为参数,实例化一个proxy对象
简单意思:Proxy类 根据要代理的对象的接口和InvocationHandler实例,先构造出代理类的字节码,然后通过传入的classloaer加载成class对象,然后在生成com.sun.proxy.$PrxoyXXX实例。要代理的对象的接口是让最后的实例和要代理的对象实现相同的功能,InvocationHandler实例是要增强的功能,
查看Proxy类的newProxyInstance方法
点击(此处)折叠或打开
Subject是被代理对象实现的接口,RealSubject是真正要被代理的对象类。在JDK实现的动态代理机制中动态代理类都要实现InvocationHandler接口,DynamicProxy就实现了这个接口,并且把要在被代理对象方法执行前(或执行后、)执行的逻辑写在invoke方法中。
下面重点看着这三段代码
Subject realSubject = new RealSubject();
这个是真正被代理的对象
InvocationHandler handler = new DynamicProxy(realSubject);
这个是代理最终被代理的对象的代理类对象。(仔细理解)
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
这个subject是个代理类对象,它是在DynamicProxy对象上实现的代理
简单说就是 这个subject代理了DynamicProxy,DynamicProxy代理了 realsubject。
看这个subject代理对象初始的方法的参数:
handler.getClass().getClassLoader() 使用同一个类加载器
realSubject.getClass().getInterfaces(),Proxy代理类所以要实现最终被代理类的所有接口中的方法
Handler,这个是关键,上一个参数告诉了代理对象要实现那些方法,怎么实现就是靠这个Handler了(通过组合的方式实现代理模式)。
具体我认为是 subject代理对象实现了realsubject中的所有方法,这个代理对象中有个成员变量是handler,在实现realsubject方法的时候调用将相应的参数传给handler,通过handler实现。
(具体传哪些参数 就看handler的invoke方法了)
在往下说的话,可以看代码handler中实现代理的方式也是通过组合的方式,handler中有个最终被代理对象subject的对象(这个和上边那个subject不是同一个对象)。
所有动态代理的原理就是
Proxy代理类--代理了-->实现InvocationHandler接口的DynamicProxy--代理了-->最终被代理的对象