背景
最近在实现一个功能,AutoConfiguration如果发现应用project定义了就不再生成。
工程目录结构如下: monitor是要deploy的工具包,demo是测试的module.
Root
-- demo
-- monitor
在demo
Module中代码如下:
package com.xxx.yyy.config;
public class ProjectConfig {
@Bean
public XXX config() {
return new XXX();
}
}
package com.xxx.yyy;
@SpringBootApplication
public class DemoApplication {
}
然后在monitor
module中代码如下:
package com.xxx.yyy.monitor;
public class JarConfigAutoConfiguration {
@Bean
@ConditionalOnMissingBean()
public XXX configX() {
return new XXX();
}
}
在测试的过程中发现总是monitor中的configX
方法先执行,而我一直记得是Spring会先执行project中的,之后才是三方jar中的。
原因
经过将近一个小时的Debug,发现这是由于package相同造成的。关键的方法是:#doProcessConfigurationClass
。
在这个方法中会扫描注有@SpringBootApplication
的DemoApplication
。(@SpringBootApplication
其实是一个复合注解,里面包括了@Configuration
)
#doProcessConfigurationClass
的处理顺序是:
- 查找component-scan,然后按classpath寻找符合的class时,因为使用的是FULL_CLASSPATH,即
classpath:*
,所以会匹配到JarConfig - 处理deferred import,这里可以理解为处理
@EnableAutoConfigurationImport
,这里会把所有的AutoConfigurationClass进行解析。 - …
验证及解决
把demo
module的package更换为与monitor
module不同,开始debug,发现正确先执行config()
方法。