一、bean的位置
spring-boot在两个位置查找bean
-
项目中的bean:只要告送spring-boot从哪个包下开始查找就可以
-
jar包中的bean:这里有两个问题
- 过滤jar包: 一个应用的jar包太多,并不是所有jar包都有bean,像apache 的工具包
- 过滤文件:jar包中的文件太多,哪些文件是bean?,如果每个文件都过滤,那效率会很低
第一个问题,通过为jar包打上一个标记来解决,spring-boot通过查找jar包下包含/META-INF/spring.factories文件来过滤jar包
第二个问题,通过在spring.factories文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration属性内容记录bean的路径,来告送spring-boot有哪些bean
二、查找bean流程
-
项目中的bean的查找
有两种方式:- @SpringBootApplication注解启动时配置
//@SpringBootApplication.scanBasePackages指定了从哪个包开始查找bean。如果不指定该属性,则会从启动类所在的包下开始查找。 @SpringBootApplication(scanBasePackages = "") public class SpringTestApplication { public static void main(String[] args) { SpringApplication.run(SpringTestApplication.class, args); } }
- @ComponentScan 注解配置
//basePackages 指定了从哪个包开始查找bean, @Configuration @ComponentScan(basePackages = { "com.test.core.config", "com.test.core.spring" }) public class TestConfiguration { }
-
jar包中的bean查找
下面是 @SpringBootApplication和@EnableAutoConfiguration 部分内容,‘->’ 代表引入。
@SpringBootApplication->@EnableAutoConfiguration->AutoConfigurationImportSelector.class
AutoConfigurationImportSelector 是实现查找的关键类,负责遍历项目中的jar包,并读取spring.factories中的内容并缓存起来。
@EnableAutoConfiguration
public @interface SpringBootApplication {}
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
//读取spring.factories文件中的 EnableAutoConfiguration属性内容
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
}
三、beanDefinition 注入
- 项目启动后会将当前
启动类
包装为beanDefinition并注入容器。 - 启动后将
org.springframework.context.annotation.ConfigurationClassPostProcessor
类注入容器,ConfigurationClassPostProcessor 会解析启动类
,处理@Configuration
、@ComponentScan
、@Import
、@ImportResource
、@Bean
并注入解析得到的beanDefinition。