Spring 中的动态代理
张大胖初学 Spring 时, 老师告诉他 Spring AOP 是基于动态代理实现的, 然后就不知所云了. 大胖工作后偶然看了篇博文, 迷迷糊糊知道了 CGlib 与 JDK Agent 都被 Spring Aop 用到了, 这两者同为动态代理技术却还是有差异的,
甚至部分差异影响了 Spring 业务项目的代码风格,
Spring AOP 默认为 AOP 代理使用标准的 J2SE动态代理。这允许代理任何接口(或接口集)。
Spring AOP 也可以使用 CGLIB 代理。这是代理类而不是接口所必需的。如果业务对象未实现接口,则默认使用 CGLIB。由于编程接口而不是类是一种很好的做法,因此业务类通常会实现一个或多个业务接口。
在需要建议未在接口上声明的方法的情况下(希望很少见),或者需要将代理对象作为具体类型传递给方法的情况下,可以强制使用 CGLIB。引用: https://docs.spring.io/spring-framework/docs/2.5.x/reference/aop.html
为什么老项目的 Service 层总是用接口+实现类 ?
相信接触过老项目的人, 一定对Service层 接口 + 实现类的方式比较眼熟. 而新项目则全部为野蛮注入, 这种情况是怎么发生的呢?
要探究这个问题, 就需要查看老版 Spring 的源码, 看看那时候有没有引入 cglib, 引入程度是如何 ?
Spring AOP 使用 JDK 动态代理或 CGLIB 为给定的目标对象创建代理.(如果您有选择,则首选 JDK 动态代理)。
如果要代理的目标对象至少实现了一个接口,则将使用 JDK 动态代理。目标类型实现的所有接口都将被代理。如果目标对象没有实现任何接口,那么将创建一个 CGLIB 代理。
如果您想强制使用 CGLIB 代理(例如,代理为目标对象定义的每个方法,而不仅仅是由其接口实现的方法),您可以这样做。但是,有一些问题需要考虑:
不能建议final方法,因为它们不能被覆盖。
引用自 Spring 2.5 docs: https://docs.spring.io/spring-framework/docs/2.5.x/reference/aop.html
笔者查看了 Spring 2.0, 3.0, 5.0,最终结果就是,spring 2.0 时期就使用 cglib 代理了,
spring项目里 bean,aop 都用了,后续版本将 cglib 以及asm依赖集中放到了 core 模块中,可能是早期受面向接口编程的影响,以及 Apache Dubbo 的影响
Cglib 在 Spring 中负责的岗位
放到以后探讨
Cglib 源码探索
放到以后探讨