Spring Boot自动装配(一)
注:基于SpringBoot2.x版本以上
@EnableAutoConfiguration
@Target({
ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({
AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {
};
String[] excludeName() default {
};
}
其中AutoConfigurationImportSelector就是具体自动装配的实现类,实现了DeferredImportSelector接口,具体的实现逻辑均在**selectImports(****)**方法中。
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
//加载自动装配的元信息。
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
//获取@EnableAutoConfiguration标注类的元信息。
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//获取自动装配类的候选类名称。
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
//去重,排除重复的configurations(为什么会重复呢?)
configurations = this.removeDuplicates(configurations);
//获取自动装配组件的排除名单。
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
//检查排除类是否合法
this.checkExcludedClasses(configurations, exclusions);
//移除所有的排除名单
configurations.removeAll(exclusions);
//进行过滤,autoConfigurationMetadata充当过滤条件。
configurations = this.filter(configurations, autoConfigurationMetadata);
//自动装配的导入事件
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}
}
疑问:
- 如何装配组件,装配哪些组件?
- 如何排除组件?
从所有的方法,一步步的分析。
AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
return loadMetadata(classLoader, "META-INF/spring-autoconfigure-metadata.properties");
}
可以从代码中看到,它加载的是spring-autoconfigure-metadata.properties
由于文件内容过多,这里仅贴了部分。
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration=
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration.AutoConfigureAfter=org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration.Configuration=
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration.ConditionalOnClass=com.datastax.driver.core.Cluster,org.springframework.data.cassandra.core.ReactiveCassandraTemplate,reactor.core.publisher.Flux
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration.ConditionalOnClass=org.apache.solr.client.solrj.SolrClient,org.springframework.data.solr.repository.SolrRepository
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration=
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration=
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration.Configuration=
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration.AutoConfigureBefore=org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.jms.artemis.ArtemisXAConnectionFactoryConfiguration=
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration.Configuration=
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration=
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources(path) : ClassLoader.getSystemResources(path);
Properties properties = new Properties();
while(urls.hasMoreElements()) <