Java动态代理实现原理

Java动态代理(dynamic proxy)实现原理
应用场景:

spring切片、权限、日志、事务管理、Mapper接口等

当你在使用这些spring集成好的功能是否也会疑惑,为什么加个注解,或者按规则创建好文件就可以实现各种功能了呢?

一、动态代理定义

顾名思义,根据源文件方法,动态生成代理类来帮助处理业务。那什么是代理类呢?为什么要生成代理类呢?为什么要动态生成呢?此中缘由请听我慢慢道来。

1.比如说你想去买火车票,但火车站很远而且人也多不方便,就可以到就近的火车票代售点购买车票,代售点就是这里所说的代理。

代理模式就是在访问类目标方法上加了一层业务处理,这层会做一些增强业务,但最终还是会调用目标方法。对外开放的是代理类,而不是原有的类。

2.在使用Spring框架的AOP特性时,使用的就是使用动态代理。之所以是动态,是在代码运行阶段在内存里生成代理类,而不是生成文件。否则一个项目里那么多的要代理的类,都生成代理类文件会导致工程庞大冗杂。

二、动态代理的实现

动态代理两种实现方式:

1.JDK动态代理实现

  • 特点

    1) 使用反射机制

    2) 实现InvocationHandler,在invoke方法添加业务逻辑,使用Proxy.newProxyInstance产生代理对象

    3) 代理类和实现类实现同一个接口,代理类有一个实现类的引用,客户调用代理类的方法时,代理类就调用实现类的方法

1
2
3
4
5
6
7
8
9
ElectricCar car = new ElectricCar();
ClassLoader classLoader = car.getClass().getClassLoader();
Class<?>[] interfaces = car.getClass().getInterfaces();
InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(car);
Object proxy = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
Vehicle vehicle = (Vehicle) proxy;
vehicle.drive();
Battery battery = (Battery) proxy;
battery.charge();

2.CGlib动态代理实现

  • 特点

    1) 使用ASM字节码处理框架

    ASM 是一个 Java 字节码操控框架。它能够以二进制形式修改已有类或者动态生成类。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类

    2) 实现 MethodInterceptor方法代理接口,创建代理类

    3) 通过继承原有方法并重写,代理类是原有类的子类,因此不能代理final修饰的方法

1
2
3
4
5
6
7
8
public static void main(String[] args) {
ProxyDriver proxyDriver = new ProxyDriver();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Verhicle.class);
enhancer.setCallback(proxyDriver);
Verhicle proxy = (Verhicle) enhancer.create();
proxy.drive();
}
三、动态代理的选择

在 Spring Boot 2.0 中,Spring Boot现在默认使用CGLIB动态代理(基于类的动态代理), 包括AOP。 如果需要基于接口的动态代理(JDK基于接口的动态代理) , 需要设置spring.aop.proxy-target-class属性为false。