欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JDK动态代理实现原理(含实例)

程序员文章站 2022-04-19 16:32:01
...

github实例:
https://github.com/hello-qiang/Java/tree/master/TestProxy

1. 动态代理概念

动态代理的意义在于生成一个 占位(代理对象),用来代理真实的对象,从而控制真实对象的访问。
代理对象的作用就是:在真实对象访问之前或者之后加入对应的 逻辑,或者根据其他规则控制是否使用真实对象。

代理分为两个步骤:

  1. 代理对象和真实对象建立代理关系
  2. 实现代理对象的代理逻辑方法

2. JDK动态代理技术

JDK动态代理是JDK自带的功能,是java.lang.reflect.*包提供的方式,他必须借助一个接口才能提供代理对象
在JDK动态代理逻辑中,要实现代理逻辑类必须要去实现java.lang.reflect.InvocationHandler接口。

JDK动态代理技术的实现步骤:

  1. 创建接口
  2. 创建接口的实现类:此类的实例对象是真实对象
  3. 创建代理类:此类必须实现InvocationHandler接口
  4. 测试

3. 动态代理相关类的介绍

在Java的动态代理机制中,有两个重要的类和接口,一个是InvocationHandler(Interface)另一个是Proxy(Class),这个类和接口是实现动态代理所必须用到的。

3.1. InvacationHandler

每一个动态代理类都必须实现InvocationHandler接口,并且每个代理类的实例都关联了一个handler, 当我们通过代理对象调用方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke方法来调用, 此时使用的是反射技术

Object invoke((Object proxy, Method method, Object[] args) throws Throwable

这个方法中三个参数代表如下:

  • proxy:指的是JDK动态生成的最终代理对象
  • method:指的是我们所要调用真实对象的某个方法的Method对象
  • arg:指的是调用真实对象的某个方法时接受的参数
  1. 关于Method类
    此类是方法的定义,提供关于类一个了或者接口中单个方法的信息和对该方法的访问。
    关于Invoke()方法:在不知到具体类的情况下,根据配置的字符串调用类中的方法。

3.2. Proxy

Proxy这个类的作用是用来动态创建一个代理对象的类,最常用的方法是newProxyInstance

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h)  throws IllegalArgumentException

这个方法的作用是得到一个动态的代理对象,其接受的三个参数所代表的含义为:

  • loader:一个ClassLoader对象,定义了由那个CLassLoader来生成代理对象进行加载。
  • interfaces:一个Interface对象数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给他,那么这个代理对象就要宣称实现了该接口,这样我就可以调用这组接口中的方法了。
  • 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

综上所述:
动态代理类是这样一个类:他是在运行时生成的class,在生成他时必须提供一组interfaace给他,然后class就宣传实现了这些interface.如此一来就可以把class的实例当作这些interface中的任何一个使用,当然这个class就是一个Proxy,不会做实质性的工作,在生成他的实例时必须提供一个handler,由他接管实际的工作。

  1. 关于ClassLoader
    ClassLoader是类加载器,就是将类或者接口的字节码文件加载到JVM中。在JDK中有多种类加载器。

4. 关于CGLIB

  1. CGLIB动态代理的优势在于不需要提供接口,只需要一个非抽象类即可。

  2. 何时使用JDK还是CGLIB?

    • 如果目标对象实现了接口,默认情况下使用JDK的动态代理实现AOP
    • 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
    • 如果目标对象没有实现接口,必须采用CGLIB库,Spring会自动在CGLIB和JDK动态代理之间转换。

参考资料:
https://blog.csdn.net/xiaokang123456kao/article/details/77679848

相关标签: jdk 动态代理