SpringBoot專題(三):自動配置原理

配置文件能配置的屬性參照:

https://docs.spring.io/spring-boot/docs/2.1.7.RELEASE/reference/htmlsingle/#common-application-properties

一、配置原理的實現

1)、SpringBoot啓動的時候加載主配置類,並開啓自動配置功能@EnableAutoConfiguration

2)、@EnableAutoConfiguration的作用:

  • 利用AutoConfigurationImportSelector給容器導入一些組件
  • 可以查看 AutoConfigurationImportSelector.java中的 selectImports{}方法的內容:
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
public String[] selectImports(AnnotationMetadata annotationMetadata) {

    AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
				annotationMetadata);
}


protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
    
    // 獲取候選的配置
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    // 掃描所有jar包類路徑下 META-INFO/ spring.factories
    // 把掃描到的這些文件的內容包裝成properties對象
    // 從properties中獲取到EnableAutoConfiguration.class類(類名)對應的值把它們添加在容器中
	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;
}

將類路徑下META-INFO/spring.factoties裏面配置的所有EnableAutoConfiguration的值加入到了容器中

# AutoConfigureDataJdbc auto-configuration imports
org.springframework.boot.test.autoconfigure.data.jdbc.AutoConfigureDataJdbc=\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

# AutoConfigureDataJpa auto-configuration imports
org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureDataJpa=\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

# AutoConfigureDataLdap auto-configuration imports
org.springframework.boot.test.autoconfigure.data.ldap.AutoConfigureDataLdap=\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration

# AutoConfigureDataMongo auto-configuration imports
org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo=\
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.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration

# AutoConfigureDataNeo4j auto-configuration imports
org.springframework.boot.test.autoconfigure.data.neo4j.AutoConfigureDataNeo4j=\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

# AutoConfigureDataRedis auto-configuration imports
org.springframework.boot.test.autoconfigure.data.redis.AutoConfigureDataRedis=\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration

# AutoConfigureJdbc auto-configuration imports
org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureJdbc=\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

# AutoConfigureTestDatabase auto-configuration imports
org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase=\
org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

# AutoConfigureJooq auto-configuration imports
org.springframework.boot.test.autoconfigure.jooq.AutoConfigureJooq=\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration

# AutoConfigureJson auto-configuration imports
org.springframework.boot.test.autoconfigure.json.AutoConfigureJson=\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration

# AutoConfigureJsonTesters auto-configuration imports
org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters=\
org.springframework.boot.test.autoconfigure.json.JsonTestersAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration

# AutoConfigureWebClient auto-configuration imports
org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient=\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientAutoConfiguration

# AutoConfigureWebFlux auto-configuration imports
org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebFlux=\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration

# AutoConfigureMockMvc auto-configuration imports
org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc=\
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration,\
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityAutoConfiguration,\
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration,\
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration

# AutoConfigureMockRestServiceServer
org.springframework.boot.test.autoconfigure.web.client.AutoConfigureMockRestServiceServer=\
org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerAutoConfiguration

# AutoConfigureRestDocs auto-configuration imports
org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs=\
org.springframework.boot.test.autoconfigure.restdocs.RestDocsAutoConfiguration

# AutoConfigureTestEntityManager auto-configuration imports
org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureTestEntityManager=\
org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration

# AutoConfigureWebClient auto-configuration imports
org.springframework.boot.test.autoconfigure.web.client.AutoConfigureWebClient=\
org.springframework.boot.test.autoconfigure.web.client.WebClientRestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration

# AutoConfigureWebMvc auto-configuration imports
org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc=\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

每一個這樣的xxxAutoConfiguration類都是容器中的一個組件,加入到容器中,用它們做自動配置;

3)、每一個自動配置類進行自動配置功能

4)、以HttpEncodingAutoConfiguration爲例解釋自動配置原理:

@Configuration  //表示這是一個配置類,可以給容器中添加組件
@EnableConfigurationProperties(HttpProperties.class) //啓動指定類的 HttpProperties.class 的ConfigurationProperties功能
@ConditionalOnWebApplication //Spring底層Condition註解,根據不同的條件,如果滿足指定的條件,整個配置類裏面的配置就會生效;判斷當前應用是否爲web應用,如果是,當前配置類生效
@ConditionalOnClass(CharacterEncodingFilter.class) //判斷當前項目中有沒有這個類攔截器CharacterEncodingFilter;SpringMVC中解決亂碼的過濾器
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) //判斷這個配置文件中是否存在這個配置: spring.http.encoding ,如果不存在,判斷也是成立的
//即使配置文件中不配置 spring.http.encoding.enabled=true ,也是默認生效,自動判定爲true
public class HttpEncodingAutoConfiguration {
    
    //已經和SpringBoot的配置文件映射了
    private final HttpProperties.Encoding properties;
    
    // 只有一個有參構造器的的情況下,參數的值就會從容器中拿	
    public HttpEncodingAutoConfiguration(HttpProperties properties) {
		this.properties = properties.getEncoding();
	}
    
    @Bean //給容器中添加一個組件,這個組件的某些值需要從properties中獲取
	@ConditionalOnMissingBean
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
		return filter;
	}

根據當前不同的條件判斷,然後決定這個配置類是否生效?

一旦這個配置類生效,這個配置類就會給容器中添加各種組件,這些組件的屬性是從對應的properties類中獲取的,這些類裏面的每一個屬性又是和配置文件綁定的。

5)、所有在配置文件中能配置的屬性的值都是在xxxProperties類中封裝着,配置文件能配置什麼功能就可以參照某個功能的對應的這個屬性類

@ConfigurationProperties(prefix = "spring.http") //從配置文件中獲取的指定的值和bean的屬性進行綁定
public class HttpProperties {

}

精髓:

1)、SpringBoot啓動會加載大量的自動配置類

2)、我們需要的功能有沒有SpringBoot默認寫好的自動配置類,

3)、如果有,看這個自動配置類中到底配置了哪些組件(只要我們用的組件有,我們就不需要再來配置了,如果沒有則需要自己添加)

4)、給容器中自動配置類添加組件的時候,會從properties類中獲取屬性,我們就可以在配置文件中指定這些屬性的值(如更改配置屬性的默認值) 。

xxxAutoConfiguration:自動配置類,給容器中添加組件

xxxProperties:封裝配置文件相關的屬性

二、配置的細節

1、@Condition派生註解(Spring註解版原生的@Condition作用)

作用:必須是@Condition指定的條件成立,纔給容器中添加組件,配置內容才生效

@Condition擴展註解 作用(判斷是否滿足當前條件)
@ConditionOnJava 系統的Java版本是否符合要求
@ConditionOnBean 容器中存在指定Bean
@ConditionOnMissingBean 容器中不存在指定Bean
@ConditionOnExpression 滿足SpEL表示指定
@ConditionOnClass 系統中有指定的類
@ConditionOnMissingClass 系統中沒有指定的類
@ConditionOnSingleCandidate 容器中只有一個指定的Bean,或者這個Bean是首選Bean
@ConditionOnProperty 系統指定的屬性是否有指定的值
@ConditionOnResource 類路徑下是否存在指定資源文件
@ConditionOnWebApplication 當前是Web環境
@ConditionOnNotWebApplication 當前不是Web環境
@ConditionOnJndi

JNDI存在指定項

自動配置類必須在一定的條件在才能生效,因此,並不是所有的配置都會在啓動的時候生效。

三、如何確定哪些配置類是生效的?

通過 properties 配置文件配置 debug=true 來讓控制打印自動配置報告,這樣就能看到哪些自動配置類生效了。

#開啓SpringBoot的Debug
debug=true

報告會顯示匹配上的和未匹配上的

============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:匹配上的
Negative matches:未匹配上的

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章