扫描文末二维码或者微信搜索公众号
小李不秃
,即可关注微信公众号,获取到更多 Java 相关内容。
1. 带着问题去学习
上一篇讲解了 JDK 的动态代理机制,JDK 动态代理的缺点:
- 问题1:JDK 动态代理是基于接口实现的,如果类不实现接口,怎么去代理这个类呢?
- 问题2:JDK 动态代理的目标类的内部调用自己的另一个方法,不会经过代理对象,那如何解决这个问题呢?
那就了解一下 Spring AOP 的另一个代理机制 cglib 动态代理。
2. CGLIB 动态代理
- 实战CGLIB系列文章之开篇:CGLIB简介、原理与应用
- 实战CGLib系列之proxy篇(一):方法拦截MethodInterceptor
- 实战CGLib系列之proxy篇(二):回调过滤CallbackFilter
- 实战CGLib系列之proxy篇(三):延迟加载LazyLoader
- 实战CGLib系列之proxy篇(四):改进版延迟加载Dispatcher
- 实战CGLib系列之proxy篇(五):接口生成器InterfaceMaker
- Spring Aop之Cglib实现原理详解
- AOP 的利器:ASM 3.0 介绍
- 学完 Aop,连动态代理的原理都不懂?
内容我抽空整理,上面这些文章有的年头比较久,看一下了解怎么使用就行。我大概总结一下上面的重点:
-
JDK 动态代理生成代理类继承 Proxy 并且实现代理接口,底层原理是通过反射调用父类的方法。
-
CGLIB 动态代理生成代理类的子类,并且实现了 Factory 接口,底层是通过 ASM 进行字节码的增强,然后生成一个新的子类。调用方法就直接调用,不需要再通过反射的方式调用。
-
Spring Boot 2.0 开始代理类默认的实现方式是 cglib,如果想使用 JDK 动态代理,可以通过 spring.aop.proxy-target-class=false 来实现。
-
CGLIB 代理的目标类调用自己的另一个方法,也是会经过代理对象的,因为底层不像 JDK 动态代理的反射方式调用,而是通过动态生成子类的全新方式调用。
-
CGLIB 代理的目标类的方法满足下面条件任意一点,就不会被代理:
- 使用 final 修饰的方法
- 使用 private 类型的方法
- 使用包访问权限
-
CGLIB 代理方法,想要对方法的返回值进行特殊处理,可以使用 CallbackFilter。
3. 总结
通过动态代理的方式增强目标方法,也是实现 Spring AOP 的原理。动态代理有两种方式:JDK 动态代理和 CGLIB 动态代理。这两种代理方式的原理我也已经讲过了,希望大家也可以去实践一下,也可以跟踪一下 Spring 的代码看看底层的原理。
最后头脑风暴一下:为什么 Spring Boot 默认使用 CGLIB 动态代理呢?
扫描下方二维码即可关注微信公众号
小李不秃
,一起高效学习 Java。