1. 程式人生 > >Spring Boot 自動配置原理application.properties

Spring Boot 自動配置原理application.properties

自動配置呢

Spring Boot spring-boot-autoconfigure 依賴做了很多預設的配置項,即應用預設值。這種模式叫做 “自動配置”。Spring Boot 自動配置會根據新增的依賴,自動載入依賴相關的配置屬性並啟動依賴。例如預設用的內嵌式容器是 Tomcat ,埠預設設定為 8080。

為什麼需要自動配置?顧名思義,自動配置的意義是利用這種模式代替了配置 XML 繁瑣模式。以前使用 Spring MVC ,需要進行配置元件掃描、排程器、檢視解析器等,使用 Spring Boot 自動配置後,只需要新增 MVC 元件即可自動配置所需要的 Bean。所有自動配置的實現都在 spring-boot-autoconfigure 依賴中,包括 Spring MVC 、Data 和其它框架的自動配置。

  1. External Configuration指的不是把配置內容分離到properties檔案裡,而是配置儲存在classpath之外,比如spring cloud config的伺服器中
  2. 自動化配置本身包含了兩塊內容:@Configuration的定義和properties屬性的定義,外部化配置是跟載入過程相關的。

  3. 自動配置原理淺析

spring-boot-autoconfigure 依賴

spring-boot-autoconfigure 依賴,是 Spring Boot 實現自動配置的核心 Starter 元件。
可以看出很多常用框架的自動配置包目錄:org.springframework.boot.autoconfigure.thymeleaf、org.springframework.boot.autoconfigure.data.jpa等

那進一步開啟包下對應的自動配置類,可以看到有:Jpa 自動配置類 JpaRepositoriesAutoConfiguration、Thymeleaf 自動配置類 ThymeleafAutoConfiguration 等

spring-boot-autoconfigure 依賴的工作原理很簡單,通過 @EnableAutoConfiguration 核心註解初始化,並掃描 ClassPath 目錄中自動配置類對應依賴。比如工程中有木有新增 Thymeleaf 的 Starter 元件依賴。如果有,就按按一定規則獲取預設配置並自動初始化所需要的 Bean。

那具體 @EnableAutoConfiguration 核心註解的工作原理是咋樣的呢?

@EnableAutoConfiguration 註解

@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 {};

}
@EnableAutoConfiguration 註解核心點是 @Import 的自動配置匯入選擇器類 AutoConfigurationImportSelector 。其程式碼部分如下:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
}

總結可得具體流程如下:

AutoConfigurationImportSelector 通過 SpringFactoriesLoader.loadFactoryNames() 核心方法讀取 ClassPath 目錄下面的 META-INF/spring.factories 檔案。
spring.factories 檔案中配置的 Spring Boot 自動配置類,例如常見的Jpa 自動配置類 JpaRepositoriesAutoConfiguration、Thymeleaf 自動配置類 ThymeleafAutoConfiguration 、 WebMvcAutoConfiguration Web MVC 自動配置類和ServletWebServerFactoryAutoConfiguration 容器自動配置類等 。
spring.factories 檔案和 application.properties 檔案都屬於配置檔案,配置的格式均為鍵值對。裡面配置的每個自動配置類都會定義相關 Bean 的例項配置,也會定義什麼條件下自動配置和哪些 Bean 被例項化。
當 pom.xml 新增某 Starter 依賴元件的時候,就會自動觸發該依賴的預設配置。
具體 Starter 元件依賴是如何觸發它的預設配置的呢?

  1. Starter 元件淺析

Starter 元件

Spring Boot 提供了很多 “開箱即用” 的 Starter 元件。Starter 元件是可被載入在應用中的 Maven 依賴項。只需要在 Maven 配置中新增對應的依賴配置,即可使用對應的 Starter 元件。例如,新增 spring-boot-starter-web 依賴,就可用於構建 REST API 服務,其包含了 Spring MVC 和 Tomcat 內嵌容器等。

一個完整的 Starter 元件包括以下兩點:

提供自動配置功能的自動配置模組。
提供依賴關係管理功能的元件模組,即封裝了元件所有功能,開箱即用。
spring-boot-starter-web 依賴原始碼

當我們新增 spring-boot-starter-web 依賴,並啟動應用會觸發容器自動配置類。容器自動配置類 ServletWebServerFactoryAutoConfiguration 的部分程式碼如下:

package org.springframework.boot.autoconfigure.web.servlet;

@Configuration
@ConditionalOnClass({ServletRequest.class})
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@EnableConfigurationProperties({ServerProperties.class})
@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class})
public class ServletWebServerFactoryAutoConfiguration {
… 省略
}

上面程式碼原始碼淺析下:

@ConditionalOnClass 註解表示對應的 ServletRequest 類在 ClassPath 目錄下面存在,並且 @ConditionalOnWebApplication 註解表示該應用是 Servlet Web 應用時,才會去啟動容器預設配置
通過 ServerProperties 類預設設定了埠為 8080
Type.SERVLET 列舉代表 Servlet Web 應用,Type.REACTIVE 列舉代表響應式 WebFlux 應用。
@ConditionalOnClass 註解類似功能的還有 @ConditionalOnMissingBean 、@ConditionalOnProperty等註解。這裡不一一列出解釋。

  1. 小結

自動配置,是一把雙刃劍。用好了就像,天下武功唯快不破一樣;用不好就需要注意一些自動化配置造成的問題。常見的問題常見有:

Spring Boot 工程新增某些 Starter 元件依賴,但不想觸發元件自動配置
Spring Boot 配置多個不同資料來源配置時,比如使用 XML 配置多資料來源,但其預設資料來源配置會觸發自動配置出現問題。
類似場景下,解決方式是排除不需要的特定自動配置類。通過 exclude 屬性指定並排除自動配置類,程式碼如下:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
也等價於配置在 @EnableAutoConfiguration 註解,程式碼如下:

@SpringBootApplication
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
自動配置會最大的智慧化,當配置了 exclude 屬性時,Spring Boot 優先初始化使用者定義的 Bean ,然後在進行自動化配置。