「小马哥技术周报」- 第七十八期 议题三:大厂技术专家带你手撕源码!Spring设计缺陷?
解决方案:
● 通过 Comparator 来控制 CommonAnnotationBeanPostProcessor以及 AutowiredAnnotationBeanPostProcessor之间的Bean 处理顺序。
还原现场(最先还原)
如何确定版本
Java 8
Spring Framework : 5.1.6.RELEASE
Spring Boot : 2.1.4.RELEASE
如何确定应用使用哪些模块
● Spring WebMVC
● Spring AOP
● Spring TX
● Spring JDBC
组件使用场景
CommonAnnotationBeanPostProcessor 使用场景
JSR-250 以及传统 Java EE 注解(可选支持,不一定存在于 Class-Path)
● 依赖注入
○ @javax.xml.ws.WebServiceRef
○ @javax.ejb.EJB
○ @javax.annotation.Resource
● 生命周期回调
○ 初始化 - @PostConstruct
○ 销毁 - @PreDestroy
问题的症结在于:
DataSourceConfig Bean 在初始化过程中依赖了自身 Bean(自我依赖,循环依赖),导致了被依赖的 Bean(自己)不完全被初始化。源代码导致了 CommonAnnotationBeanPostProcessor在 AutowiredAnnotationBeanPostProcessor之前被执行。
原视频中之所以能解决是因为代码调整了 AutowiredAnnotationBeanPostProcessor 与 CommonAnnotationBeanPostProcessor之间的加载顺序,使其正确。
DataSourceConfig Bean 编程方式是没有问题,理论上 Spring Framework 应该予以支持,因为默认 BeanProcessor 执行顺序是 AutowiredAnnotationBeanPostProcessor在 CommonAnnotationBeanPostProcessor之前。
BeanDefinition 定义顺序是 AutowiredAnnotationBeanPostProcessor在 CommonAnnotationBeanPostProcessor之前。
由于 AutowiredAnnotationBeanPostProcessorOrder 数值高于 CommonAnnotationBeanPostProcessor的 Order 数值,所以优先级是 CommonAnnotationBeanPostProcessor高于 AutowiredAnnotationBeanPostProcessor。(直到最新版本也是如此。)
所以 DataSourceConfig Bean 在用法上需要注意这个细节。