JDK动态代理源码解析

82 阅读2分钟

环境

在这里插入图片描述

在这里插入图片描述 运行: 在这里插入图片描述

源码解读

在这里插入图片描述 我们发现通过Proxy类的方法返回了一个代理类对象,传入了三个参数,分别时类加载器、被代理类、自定义类实现InvocationHandler接口并重写invoke方法实现增强。 进入该方法查看: 在这里插入图片描述 这个方法包括三个重要步骤: 步骤1:根据接口和类加载器通过反射构造代理类 步骤2:根据参数获取构造器,这个参数是InvocationHandler类 在这里插入图片描述 步骤3:通过构造器和传入的InvocationHandler创建代理对象 我们先查看代理类: 在这里插入图片描述 可以看到代理类继承了Proxy类并且实现了代理类的接口,其包含了五个方法名,这些方法名在类加载时就被初始化:

在这里插入图片描述 这个构造方法调用了父类的构造方法,查看: 在这里插入图片描述 其继承了父类的InvocationHandler属性,并调用了父类的构造方法对InvocationHandler进行了赋值。 我们查看代理类的方法: 在这里插入图片描述 当调用代理对象的方法时,会被中转到InvocationHandler对象中的invoke方法中,如下图: 在这里插入图片描述

增强逻辑

自定义一个类实现InvocationHandler接口,调用Proxy的newProxyInstance在运行时会创建一个代理类,这个代理类继承了Proxy并且实现了被代理类接口,创建代理对象时传递了传入的InvocationHandler实现类,通过父类完成初始化和InvocationHandler的赋值,当调用代理对象的方法时都会中转到InvocationHandler实现类的invoke方法中,通过增强逻辑后,通过反射调用原方法。

JDK动态代理的区别

生成代理类的方式:JDK基于反射生成代理类(继承Proxy实现被代理接口),CGLIB通过ASM字节码库生成代理类(继承被代理类)

对被代理类要求:JDK要求被代理类是个接口,CGLIB要求被代理类可以被继承,不能被final修饰

代理增强后如何调用原方法:JDK通过反射调用原方法,CGLIB通过FastClass的索引调用