Java动态代理(dynamic proxy)实现原理
应用场景:
spring切片、权限、日志、事务管理、Mapper接口等
当你在使用这些spring集成好的功能是否也会疑惑,为什么加个注解,或者按规则创建好文件就可以实现各种功能了呢?
一、动态代理定义
顾名思义,根据源文件方法,动态生成代理类来帮助处理业务。那什么是代理类呢?为什么要生成代理类呢?为什么要动态生成呢?此中缘由请听我慢慢道来。
1.比如说你想去买火车票,但火车站很远而且人也多不方便,就可以到就近的火车票代售点购买车票,代售点就是这里所说的代理。
代理模式就是在访问类目标方法上加了一层业务处理,这层会做一些增强业务,但最终还是会调用目标方法。对外开放的是代理类,而不是原有的类。
2.在使用Spring框架的AOP特性时,使用的就是使用动态代理。之所以是动态,是在代码运行阶段在内存里生成代理类,而不是生成文件。否则一个项目里那么多的要代理的类,都生成代理类文件会导致工程庞大冗杂。
二、动态代理的实现
动态代理两种实现方式:
1.JDK动态代理实现
特点
1) 使用反射机制
2) 实现InvocationHandler,在invoke方法添加业务逻辑,使用Proxy.newProxyInstance产生代理对象
3) 代理类和实现类实现同一个接口,代理类有一个实现类的引用,客户调用代理类的方法时,代理类就调用实现类的方法
|
|
2.CGlib动态代理实现
特点
1) 使用ASM字节码处理框架
ASM 是一个 Java 字节码操控框架。它能够以二进制形式修改已有类或者动态生成类。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类
2) 实现 MethodInterceptor方法代理接口,创建代理类
3) 通过继承原有方法并重写,代理类是原有类的子类,因此不能代理final修饰的方法
|
|
三、动态代理的选择
在 Spring Boot 2.0 中,Spring Boot现在默认使用CGLIB动态代理(基于类的动态代理), 包括AOP。 如果需要基于接口的动态代理(JDK基于接口的动态代理) , 需要设置spring.aop.proxy-target-class属性为false。