@SpringBootApplication注解内部
可以看到该注解上的常规注解有这几个:
- @Target : 用来指明@SpringBootApplication这个注解添加的位置
- @Retention :用来指定@SpringBootApplication这个注解的生命周期
- @Documented :添加后@SpringBootApplication这个注解可以出现在帮助文档
- @Inherited:表示@SpingBootApplication这个注解可以被子类继承
三个重要注解
现在来看后面三个比较重要注解
@SpringBootConfiguration
可以看到除了常规注解@Target@Retention@Documented外只多了两个注解
@Configuration:用来指明该类也是配置类
@Indexed:用来加速应用启动
@ComponentScan
用来指定默认组件的扫描范围,默认是当前包及其子包
注意:如果手动配置了扫描范围,则默认的扫描会失效
通过上面可以看出来以上注解都不是自动装配的核心,那么真相只有一个
@EnableAutoConfiguration
@EnableAutoConfiguration
来看@EnableAutoConfiguration内部
可以看到它除了常规注解外,多了两个@AutoConfigurationPackage和@Import注解
@AutoConfigurationPackage:指定SpringBoot默认扫描包
那么关键就在@Import这个注解,我们先看看下这个注解的作用
@Import
可以将其中的类添加给IOC容器管理,这里添加了AutoConfigurationImportSelector.class
来看这个类
AutoConfigurationImportSelector类
我们可以看到他实现的第一个接口就是DeferredImportSelector,来看DeferredImportSelector这个接口
DeferredImportSelectorr又继承了ImportSelector类,来看ImportSelector这个类
可以看到类有两个方法
1、selectImports
2、getExclusionFilter
而getExclusionFilter用default修饰有了默认实现,return null ;
因此关键就在selectorImports这个方法,说明下:
该方法的返回值是字符串数组,该数组中所有类都会被IOC容器管理
那么AutoConfigurationImportSelector作为其继承类,就需要重写该方法。我们来看下在AutoConfigurationImportSelector中重写的SelectorImports方法
selectImports方法
可以看到该方法返回的是autoConfigurationEntry.getConfigurations()
而autoConfigurationEntry是this.getAutoConfigurationEntry方法获取的
来看getAutoConfigurationEntry方法
可以看到该方法返回的AutoConfigurationEntry对象有两个重要属性
configurations和exclusions,通过名字可以判断出configurations集合就是关键
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
来看这个集合怎么获取的,通过getCandidateConfigurations方法
getCandidateConfigurations方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));
ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
通过代码我们可以看到他是读取
META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
这个两个文件,将其中数据封装到configurations集合中。那么该文件中是什么内容呢
一百多个配置类的全类名
注意:并不是AutoConfiguration文件中所有类都装入IOC容器中。需要满足@ConditionalOnMissingBean条件判断来判断是否交给IOC管理