动态代理
来源:互联网 发布:中国人工智能技术发展 编辑:程序博客网 时间:2024/05/21 21:38
一、引言
动态代理在运行期生成代理类,为什么要用动态代理设计模式? 因为真实类的接口有可能改变,如果使用静态代理会增加后期的维护成本,当然这只是其中的一个原因。
二、真实类与代理类
2.1 真实类
public class RealObject implements RealInterface{@Overridepublic void doSomething() {System.out.println("真实类做了一些事情");}@Overridepublic void doEleseSomething() {System.out.println("真实类做了一些其他事情");}}2.2 代理类(这个知识预期生成的代理类)
public class ProxyObject{ private static doSomething m1; private static doEleseSomething m2; private realObject r; private ProxyObject(realObject r) { this.r=r; } public final void doSomething () throws { Method.invoke(ro,m1); } public final void doEleseSomething() throws { Method.invoke(ro,m2); }2.3 JVM 在运行期真实生成的动态代理类
public final class $Proxy0 extends Proxy implements HelloWorld { private static Method m1; //基于真实类的接口,经过反射,生成了真实类已经实现了方法 private static Method m3; private static Method m2; private static Method m0; public $Proxy0(InvocationHandler var1) throws { //将InvocationHandler 当做参数传入 super(var1); } public final void sayHello() throws {//当用代理类访问次方法的时候,就能对应的知道真实类方法m3 try { super.h.invoke(this, m3, (Object[])null); //Proxy 持有InvocationHandler对象,可以调用invoke } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } }........................
从2.3JVM生成的真实代理类可以看出,想要生成代理类,代理类必须实现真实类的所有方法,即真实类和代理类采用相同的接口,所以必须给代理类传入真实类实现的接口数组,重点重点重点!!!
三、如何动态生成代理类
动态生成代理的是三要素:真实类、调用处理类、利用Proxy.newProxyInstance生成代理类
3.1 真实类:实现了 RealInterface接口
public class RealObject implements RealInterface{@Overridepublic void doSomething() {System.out.println("真实类做了一些事情");}@Overridepublic void doEleseSomething() {System.out.println("真实类做了一些其他事情");}}3.2 调用处理类:实现InvocationHandler接口,重现invoke方法
public class DynamicProxyHandler implements InvocationHandler {private RealObject real;public DynamicProxyHandler(RealObject real) {this.real=real;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//proxy:真实对象 method:真实对象的方法, Object:真实对象的方法所需要的参数return method.invoke(real, args);}}这个类两个作用:1)持有真实类的引用 2)invoke根据传入的Method参数,直接调用真实类的method方法。
3.3 利用Proxy.newProxyInstance生成动态代理类
public static void main(String[] args) throws NoSuchMethodException, SecurityException, Throwable {RealObject real=new RealObject(); //生成真实类InvocationHandler handler=new DynamicProxyHandler(real); //代理类持有真实类RealInterface iReal=(RealInterface) Proxy.newProxyInstance(proxy.getClass().getClassLoader(), real.getClass().getInterfaces(), handler);iReal.doSomething();}
注:Proxy.newProxyInstance方法有三个参数:第一个参数是类加载器对象(即哪个类加载器来加载这个代理类到 JVM 的方法区),第二个参数是接口(表明你这个代理类需要实现哪些接口),第三个参数是调用处理器类实例(指定代理类中具体要干什么)。
传入第二个参数使得2.3所动态生成的代理类与真实类实现同样的接口,即有同样的方法。
传入第三个参数使得2.3所动态生成的代理类的每个方法都可以通过以下方式调用:
super.h.invoke(this, m3, (Object[])null);
其中的h就代表传入的第三个参数,h.invoke其实就是在调用3.2中的invoke方法
四、动态代理的过程
1、根据3.3生成如2.3的代理类
2、执行以下方法,就相当于抵用2.3代理类相应的doSometing()方法
iReal.doSomething()
3、2.3代理类的doSometing()方法会执行以下代码
其中m3会根据你调用的方法动态生成Method dosomething这个实例
super.h.invoke(this, dosomething, (Object[])null);
4、最后实际调用3.2调用处理类的invoke方法
5、invoke方法动态抵用真实类的dosomething(),返回结果
以上是整个动态代理的过程,以前看了几次,每次都有新的体会,这次就写下来分享一下,如有错误,请指正批评!
最后说一句,如果真实类没有实现任何接口(只有真实类自己的方法),按照以上叙述,就无法动态生成方法,答案是:JVM会采用CGLIB生成代理类
阅读全文
0 0
- 代理-->静态代理&动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 动态代理
- 欧拉筛及例题
- 20171119
- Spring复习
- PreparedStatement批量处理和事务代码
- 进一步理解setTimeout与setInterval
- 动态代理
- 《Angular之命令大全》
- 作业 7
- C++继承详解
- VS2013 VTK8.1 安装配置
- Error:The authenticity of host 'github.com (192.30.255.112)' can't be established.
- Hadoop 委任和解除节点(DataNode和NodeManager) Hadoop 集群管理员经常需要向集群中添加或者移除节点。通常情况下,节点同时运行DataNode和NodeManager。
- 数据库系统的结构
- HTML游戏2