Java动态代理

什么是动态代理?

动态代理是一种代理机制,动态是相对于静态来说的。

代理可以看做是调用目标的一个包装,通常用来在调用真实目标之前进行一些逻辑处理。

  • 静态代理:是我们预先写好的一个代理类,在编译后,生成一个 class 文件。
    • 静态代理需要我们为每个目标类写对应的代理类。
  • 动态代理:在运行时生成代理类,并加载到 JVM 中。
    • 相比于静态代理更加灵活,可以通过指定目标来动态生成代理类。

代理也是一种解耦,调用者与目标类之间的解耦。在某种情况下,调用者不能或不想直接引用另一个对象,这时代理对象可以在调用者和目标之间起到中介的作用。

常见的动态代理

  • JDK 动态代理

  • CGLIB

JDK 动态代理实现步骤

  1. 定义一个目标类(被代理对象类)和一个目标类实现的接口;

  2. 实现一个 InvocationHandler(调用处理器,实现 InvocationHandler 接口)得到一个切面类(自定义实现的调用处理器),实际是将代理类中处理的业务放到 InvocationHandler的方法中完成;

  3. 然后利用 Proxy 根据目标类的类加载器、接口和切面类(自定义实现的调用处理器)得到一个代理类;

    代理类的逻辑就是把所有接口方法的调用,转发到切面类的 invoke() 方法上,在 invoke() 方法中做一些增强的处理,然后利用反射调用目标类的方法。

JDK 动态代理主要涉及到的类

  1. java.lang.reflect.InvocationHandler: 生成代理类前需要实现InvocationHandle 接口的 invoke() 方法,将代理类要实现的业务逻辑写在里面,以供后面运行时生成的代理类调用;
  2. java.lang.reflect.Proxy: 生成代理类的主类。通过 Proxy 类生成的代理类都继承了 Proxy 类。Proxy的主要调用方法为 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) –> 一个静态方法
    • 第一个参数为类加载器,通常为目标类(被代理类)的类加载器,即通过类加载器加载代理类到 JVM 的方法区;
    • 第二个参数为被代理类所有实现的接口,一个数据,通常可能为一个接口;
    • 第三个参数为自定义实现的调用处理器 InvocationHandler

为什么 JDK 动态代理要求目标类一定要定义接口?

答: 因为 Java 单继承的特性,生成的动态代理类一定要继承 Proxy 类,所以动态代理只能针对接口代理。

这点可以通过反编译运行时动态生成的代理类得到。

如何获得运行时动态生成的类?

1
2
3
4
// 运行时动态生成的代理类
public final class $Proxy0 extends Proxy implements AccountService {
}
// 从上面类的定义可知,代理类必须继承 Proxy 类,只能对接口代理。

CGLIB 的实现步骤

GCLIB 是通过字节码生成技术来实现调用的逻辑。

TODO

思考:

动态代理,装饰者模式,和类的继承 之间的区别?

最终目的:对原有/指定方法进行功能上的扩展
在不修改原业务的基础上,基于原业务方法,进行重新的扩展,实现新的业务。

Java 反射

java反射可以通过
getConstructor,getField和getMethod
以及相应的
getDeclaredConstructor,getDeclaredField和getDeclaredMethod分别获取构造方法,域和方法

区别在于getDeclaredXXX方法只会获取该类自身声明的内容,而不会获取继承来的内容

由于数组的特殊性,Array类提供一组特殊方法供反射使用

Object array = Array.newInstance(String.class, 10); //等价于 new String[10]
Array.set(array, 0, "Hello");  //等价于array[0] = "Hello"
Array.set(array, 1, "World");  //等价于array[1] = "World"
System.out.println(Array.get(array, 0));  //等价于array[0]

反射对于泛型的处理,如List
正常情况下,运行时,JVM看到的是原始类型,List,看不到List

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2022-2023 ligongzhao
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信