Spring集成其他框架,一般都是通过注解@EnableXXX的方式,在@EnableXXX注解中会有@import注解,@import导入的Bean(有3种方式:@import({ 类名.class , 类名.class… });importSelector;importBeanDefinitionRegistrar)其实就是集成框架的关键Bean。
自定义配置类如果项目中已经有默认的组件A配置(通过@import),此时我们自己要自定义一个组件A配置(通过@Bean,@Component,@import等方式)来达到一个扩展性,那么就需要控制默认配置和自定义配置之间的顺序,来保证自定义的配置会覆盖默认的配置。importSelector的方式无法控制顺序,所以需要用DeferredimportSelector来保证默认配置延迟导入解析。这样就会先解析通过@Bean,@Component,@import等方式导入的自定义配置,在最后解析默认配置时如果发现我们已经配置了相同的组件,那么就不再使用默认的配置(@ConditionalOnBean)。
DeferredimportSelector原理DeferredimportSelector除了有延迟的特性,还有分组的特性。
DeferredimportSelector通过getimportGroup看是否返回一个自定义分组Group:如果有,就会调用自定义分组中的process方法进而调用自定义分组的selectimports方法;如果没有,就会调用importSelector的selectimports方法,该方法的排序只会影响该分组中的顺序,不会影响整个容器的顺序。
SpringBoot把Bean都管理在spring.factories中,然后进行读取,读取出来所有jar包中的spring.factories之后,把里面String类型的全类名放到list中交给spring注册成BeanDefinition。
源代码 @EnableAutoConfigurationSpringBoot启动类,其中@SpringBootApplication注解表示是SpringBoot应用
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication注解,其中@EnableAutoConfiguration表示启用自动配置
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@EnableAutoConfiguration注解,其中就有@import(AutoConfigurationimportSelector.class),就是通过importSelector的方式导入一个class
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@Inherited
@AutoConfigurationPackage
@import(AutoConfigurationimportSelector.class)
public @interface EnableAutoConfiguration {
AutoConfigurationimportSelector
AutoConfigurationimportSelector实现了DeferredimportSelector,重写getimportGroup返回自定义分组AutoConfigurationGroup。从AutoConfigurationGroup#process入手:
public class AutoConfigurationimportSelector implements DeferredimportSelector, BeanClassLoaderAware,ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
...
//该方法会返回所有的自动配置类
protected AutoConfigurationEntry getAutoConfigurationEntry(Annotationmetadata annotationmetadata) {
if (!isEnabled(annotationmetadata)) {
return EMPTY_ENTRY;
}
//获取@EnableAutoConfiguration的所有属性:exclude、excludeName
AnnotationAttributes attributes = getAttributes(annotationmetadata);
//从所有jar包的meta-INF/spring.factories中获得候选的自动配置类
List configurations = getCandidateConfigurations(annotationmetadata, attributes);
//去重
configurations = removeDuplicates(configurations);
//获取需要排除的类
Set exclusions = getExclusions(annotationmetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 通过读取spring.factories中的AutoConfigurationimportFilter(包括OnBeanConditionOnClassConditionOnWebApplicationCondition等)进行过滤
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationimportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
...
@Override
public Class extends Group> getimportGroup() {
return AutoConfigurationGroup.class;
}
...
private static class AutoConfigurationGroup
implements DeferredimportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {
...
@Override
public void process(Annotationmetadata annotationmetadata, DeferredimportSelector deferredimportSelector) {
...
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationimportSelector) deferredimportSelector)
.getAutoConfigurationEntry(annotationmetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationmetadata);
}
}
//排序,只会对当前组中的类进行排序
@Override
public Iterable selectimports() {
if (this.autoConfigurationEntries.isEmpty()) {
return Collections.emptyList();
}
Set allExclusions = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
Set processedConfigurations = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
.collect(Collectors.toCollection(linkedHashSet::new));
processedConfigurations.removeAll(allExclusions);
return sortAutoConfigurations(processedConfigurations, getAutoConfigurationmetadata()).stream()
.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
.collect(Collectors.toList());
}
...
}
getCandidateConfigurations
AutoConfigurationGroup#process会调用getAutoConfigurationEntry,其中getCandidateConfigurations会从所有jar包的meta-INF/spring.factories(K-V形式)中获得候选的自动配置类,但并不是文件中的所有key都需要,只需要key为EnableAutoConfiguration(getSpringFactoriesLoaderFactoryClass)的类;
protected ListgetCandidateConfigurations(Annotationmetadata metadata, AnnotationAttributes attributes) { List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); ... } //表示只需要EnableAutoConfiguration的key的类 protected Class> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }
springboot官方配置的spring-boot-autoconfigure-2.3.6.RELEASE.jar!/meta-INF/spring.factories示例:
其中包含key为EnableAutoConfiguration的类有100多个(不同版本数量会有差异),这些配置类就提供了不同的第三方框架所需要的Bean,这些配置类当中也不是所有都需要,还会根据我们导入的starter进行匹配生效。
# Initializers org.springframework.context.ApplicationContextInitializer= org.springframework.boot.autoconfigure.SharedmetadataReaderFactoryContextInitializer, org.springframework.boot.autoconfigure.logging.ConditionevaluationReportLoggingListener # Application Listeners org.springframework.context.ApplicationListener= org.springframework.boot.autoconfigure.BackgroundPreinitializer # Auto Configuration import Listeners org.springframework.boot.autoconfigure.AutoConfigurationimportListener= org.springframework.boot.autoconfigure.condition.ConditionevaluationReportAutoConfigurationimportListener # Auto Configuration import Filters org.springframework.boot.autoconfigure.AutoConfigurationimportFilter= org.springframework.boot.autoconfigure.condition.OnBeanCondition, org.springframework.boot.autoconfigure.condition.OnClassCondition, org.springframework.boot.autoconfigure.condition.onWebApplicationCondition # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration= org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration, org.springframework.boot.autoconfigure.aop.AopAutoConfiguration, org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration, org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration, org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration, org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration, org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration, org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration, org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration, org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration, org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration, org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration, org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration, org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration, org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration, org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration, org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration, org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration, org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration, org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration, org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration, org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration, org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration, org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration, org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration, org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration, org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration, org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration, org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration, org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration, org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration, org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration, org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration, org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration, org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration, org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration, org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration, org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration, org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration, org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration, org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration, org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration, org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration, org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration, org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration, org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration, org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration, org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration, org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration, org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration, org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration, org.springframework.boot.autoconfigure.session.SessionAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration, org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration, org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration, org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration, org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration, org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration, org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration, org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration, org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration, org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration, org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration, org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration, org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration, org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration # Failure analyzers org.springframework.boot.diagnostics.FailureAnalyzer= org.springframework.boot.autoconfigure.data.redis.RedisUrlSyntaxFailureAnalyzer, org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer, org.springframework.boot.autoconfigure.flyway.FlywayMigrationscriptMissingFailureAnalyzer, org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer, org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer, org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer, org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer # Template availability providers org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider= org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider, org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider, org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider, org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider, org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvidergetConfigurationClassFilter().filter
读取spring.factories中的AutoConfigurationimportFilter,根据OnBeanCondition,OnClassCondition,OnWebApplicationCondition等条件对读取到的配置类进行过滤,决定哪些配置可以生效。
比如配置类A(onClassCondition=B),只在当前类路径中有B这个类的时候会生效,否则不生效。
private ConfigurationClassFilter getConfigurationClassFilter() {
if (this.configurationClassFilter == null) {
List filters = getAutoConfigurationimportFilters();
...
}
...
protected List getAutoConfigurationimportFilters() {
//读取spring.factories中的AutoConfigurationimportFilter
return SpringFactoriesLoader.loadFactories(AutoConfigurationimportFilter.class, this.beanClassLoader);
}
过滤就是根据当前配置的启动器starter决定哪些生效,比如当前只配置3个starter,留下来的配置类只剩下26个。
@Conditional派生注解org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-test test
| @Conditional扩展注解 | 指定条件 |
|---|---|
| @ConditionalOnJava | 系统的java版本是否符合要求 |
| @ConditionalOnBean | 容器中存在指定Bean; |
| @ConditionalOnMissingBean | 容器中不存在指定Bean; |
| @ConditionalOnexpression | 满足SpEL表达式指定 |
| @ConditionalOnClass | 系统中有指定的类 |
| @ConditionalOnMissingClass | 系统中没有指定的类 |
| @ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
| @ConditionalOnProperty | 系统中指定的属性是否有指定的值 |
| @ConditionalOnResource | 类路径下是否存在指定资源文件 |
| @ConditionalOnWebApplication | 当前是web环境 |
| @ConditionalOnNotWebApplication | 当前不是web环境 |
| @ConditionalOnJndi | JNDI存在指定项 |
springboot利用@import注解导入DeferredimportSelector(延迟加载、分组排序),基于importSelector的类可以批量导入class,所以可以读取所有jar包中的spring.factories,从spring.factories中获得候选的自动配置类,然后进行过滤,最后将读取的配置类返回一个list,返回之后spring就会将list中的类注册成BeanDefinition。



