什么是自动装配?
SpringBoot相比于Spring,优点之一就在于实现了自动装配机制,也就说不需要去写大量的xml配置文件或是写大量的@Configuration类了,通过自动装配机制就可以达到“开箱即用”的效果。所谓“开箱即用”的效果就是说:添加pom依赖,然后就可以使用了,最多是在yml或是properties文件中写一点必要的配置。那么这个自动装配机制是如何实现的呢?
如何实现自动装配?
通过一个注解来实现:
@SpringBootApplication
。
由源码可知,这个注解由以下三个注解组成(其他几个注解不重要):
@SpringBootConfiguration:其实就是个@Configuration
@ComponentScan:默认扫描与Application.java同级目录下的所有component
@EnableAutoConfiguration: 这个作用相当于是
把需要用到的@Configuration配置类全部Import进来
,其源码如下:
这个注解之所以可以做到吧把其他@Configuration配置类引入进来,靠的就是:@Import(EnableAutoConfigurationImportSelector)。
EnableAutoConfigurationImportSelector:
EnableAutoConfigurationImportSelector:其父类AutoConfigurationImportSelector的方法selectImports()做了最关键的事情:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
- 首先读取了META-INF/spring-autoconfigure-metadata.properties中的元素据信息;
- 然后在getCandidateConfigurations()中获取了META-INF/spring.factories配置文件中的key名称等于org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置项的类名列表configurations;
- 然后对configurations进行了去重、排序、排除、过滤等操作;
- 最后在fireAutoConfigurationImportEvents()中,AutoConfigurationImportEvent执行onAutoConfigurationImportEvent,其实就是让beanFactory记录好对应的configurations。
最关键的还是第二步,读取所有依赖的classpath下的META-INF/spring.factories配置文件中的内容,这个配置文件内容格式是key1=value1,key2=value2这样的格式,而EnableAutoConfigurationImportSelector会去读取key为org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的value值,它的value值是逗号分隔的类名列表,这些类都是直接或间接标注了@Configuration的类配类。
EnableAutoConfigurationImportSelector这个类就像是八爪鱼一样,把所有需要的配置类全部抓取过来集中到一处,以便于进行自动装配。
而对于所有要加入的依赖来说,可以制作成一个xxx-starter.jar(写一个配置类A,里面的属性可以写一些默认值,然后写spring.factories:org.springframework.boot.autoconfigure.EnableAutoConfiguration = 配置类A,最后放到META-INF目录下即可),应用只要依赖这个xxx-starter,在应用启动的时候SpringBoot就会进行自动装配,从而实现“开箱即用”的效果。