Spring同包同名的配置类处理方式

同包同名的配置类Spring是如何处理的?

先看一下测试用例

项目结构
项目结构
项目结构
项目结构
运行结果

很遗憾加载了ServiceA,为什么会出现这种情况,我们下面分析一下


为什么会导致这种现象?

扫描的实现类为ClassPathBeanDefinitionScanner,Spring中所有的秒扫方法实现都是委托到这个类来处理的,我们直接看最原始的扫描结果.可以明显看到这里虽然同包同名但是file的路径是不同的,所以在扫描处理这个阶段是可以区分的,但是实际上变为ScannedGenericBeanDefinition这个对象的时候,它的基类AbstractBeanDefinition的equals方法经过自身的重写,并没有去考虑实际Resource的不同.也就是存在同包同名的Class这里也只会注册到容器一个对象(同包同名后面的会替换掉前面的).

可是虽然同包同名,但是我们通过@Profile进行了区分,这里应该是会把那个不满足条件的Class跳过才对,也就是应该加载了对的那个Class.这里确实是加载的对的那一个,那么为什么加载了对了那个BeanDefinition我们的注解却没有生效呢?这里实际上只解析了指定路径扫出来的结果,并没有处理配置类的递归解析,我们继续往下看看配置类的注解如何解析的.

运行分析

这里看到一旦扫描完成直接判断扫描到的BeanDefiition是否含有配置类@Configuration注解,如果有的话递归解析,但是parse方法并没有直接使用这个BeanDefiition已经解析出的注解而是自己从新加载

运行分析
运行分析
运行分析

可以看到这里加载了错误的元信息回去,但是实际上这里解析不会出问题的,因为processConfigurationClass方法会判断@Conditional注解的条件.

运行分析

到这里都没有载入错误的信息,那到底这些错误的注解实在哪里解析的?继续往下看,追踪到所有解析的入口在ConfigurationClassPostProcessor的processConfigBeanDefinitions方法.

先看一下主要的相关逻辑.去除了部分其他逻辑细节

运行分析

在第一次扫描完之后原来外层还会再判断一次配置类是否加载,这里可是从BeanDefiition取出来正确的元信息了,那么会加载正确吗?

运行分析
运行分析

下面就找到了最终加载错误的元凶了...

运行分析
运行分析
运行分析

可以看到最后还是通过正确的BeanDefinition跳过验证,后面通过缓存加载了错误的类元信息,导致后面解析类元信息解析错误.


3总结

尽量避免同包,每个项目的package都应该有自己独立的顶层package这样能避免同包同名导致的错误.相同包内如果同名会提示错误的,所以同项目同包目录下不担心同名问题.


4其他

示例源码:github源码地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,946评论 6 342
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,132评论 25 708
  • 【60天月度檢視】郭志斌 第一组郭思彤家长 郭志斌 作者 2017.10.01 22: 00 【基本情況】 姓名:...
    配誌阅读 354评论 0 0
  • 今天要跟大家讲的故事,发生在2007年,也就是十年前,同样是这样一个凉爽的季节,韩旭和敬文他们相识了。他们的第一次...
    劉建業阅读 207评论 0 0
  • 感觉有更多优秀的订阅号,有许多的大伽,有些观点都有些重复,或者是在哪里已经看到过得,所以我觉得应该花时间把基础课学...
    莉香读书阅读 171评论 0 0