Spring Boot自動配置


本文主要介紹spring boot的神器之一,自動配置,主要從以下幾個方面介紹自動配置:

  1. 先決條件Starter
  2. spring.factories機制
  3. Enable系列注解
  4. 自動配置原理
  5. 自動配置實例分析
  6. 創建自己的Starter和自動配置

一.先決條件Starter

spring boot自動配置(如,web自動配置、數據源自動配置、redis自動配置等等)能夠起作用的很大前提是基於Starter的應用。往往只要引用進某個模塊的Starter,spring boot就能自動配置。比如引進spring-boot-starter-web,只需要在yml或者properties中配置:

  • server.port
  • server.context

就能啟動spring boot應用,快速完成web應用的開發。而非像傳統web工程那樣需要配置復雜的web項目描述符web.xml等。其中就是因為spring boot根據依賴的spring-boot-starter-web,然后進行web方面的自動配置,比如創建web容器,DispatcherServlet。

既然Starter如此重要,它到底是什么?

Starter是一組非常方便的依賴集合,簡單點說就是maven pom,不過該pom中聚合了一個模塊相關的依賴。應用不需要再單獨依賴,只需要依賴Starter,就可以一站式解決所需的依賴,對於自定義的starter甚至更能解決自動配置的依賴。如web應用,需要單獨依賴tomcat、jsp-servlet、spring-web、spring-webmvc,但是spring boot只需要依賴spring-boot-starter-web,就可以將這些單獨依賴全部依賴進你的應用,機器方便的同時,也解決了版本沖突和兼容問題。

以spring-boot-starter-web為例,分析下它的結構:

從以上的starter結構上來看,可以看出幾點:

  1. starter的作用主要是模塊化依賴,一站式解決單獨依賴問題。因為starter中並沒有任何java code。
  2. starter中有個spring.providers文件,該文件主要是為了提供給STS或者一些IDE檢測識別需要的依賴,並沒有實際具體作用
  3. starter的一站式依賴的同時還生效自動配置,因為只要依賴starter,啟動時就可以自動配置

pom.xml中依賴如下:

pom中依賴了spring-web、spring-webmvc、starter-tomcat。通過starter可以一站式解決maven依賴問題。

至於第三點通過starter生效自動配置,在讀完自動配置原理后,實例分析時再進行詳解。那時更能深刻而透徹的理解它。


二.spring.factories機制

前面講的starter,是自動配置的依賴基石,那么spring.factories機制就是自動配置的擴展載入策略。

自動配置需要依賴大量spring java configuration,這些配置往往都放在spring-boot-autoconfigure模塊中(一般不會單獨依賴這個模塊pom,而是通過依賴starter的方式,后面實例分析是詳解)。

然而這些配置如何被spring掃描解析,無非就以下幾種形式:

  1. 通過制定scan package形式,讓spring掃描
  2. 通過類似Java SPI機制將其載入

顯然第一種方式不適合,因為每個模塊的自動配置package都不一樣,若要讓應用開發者配置scan pacakge,不僅需要開發者關注autoconfigure的機制,而且也與自動相違背。

第二種方式便可以做到對應用開發者的透明處理,擴展性極好。spring.factories機制就是類似於Java SPI,在類路徑上有個spring.factories文件,其中存需要自動配置的Java Configure類,然后通過Spring Factory Loader將其載入,作為spring的configuration class。

首先看下spring-boot-autoconfigure模塊中的spring.factories:

在自動配置模塊中都有這個文件,用於動態加載configuration class。再來看下其中內容:

該文件中存了大量的配置類,提供給spring加載作為configuration class,進行解析注冊相應的Bean,這樣就完成了自動配置,從而避免應用開發者手動配置的不便。
比如:org.springframework.boot.autoconfigure.aop.AopAutoConfiguration完成了spring aop的自動配置,這個自動配置中主要配置了spring aop需要的配置,從而避免日常非spring boot應用配置apo時,需要配置的一些基礎apo配置(aop:aspectj-autoproxy,或者@EnableAspectJAutoProxy)。

通過以上的了解,更進一步理解自動配置,其實就是將以前非spring boot應用需要配置的大量Bean或者其他的基礎配置(路徑掃描、aop基礎配置,或者數據源Bean)等等應用需要的基礎配置遷移至已經固有的autoconfigure模塊中,將其固化,從而減少甚至避免應用開發者再去進行手動配置,以提高應用開發的便捷。應用開發者只需要將所需的自動配置模塊依賴進來,然后由spring自身進行自動化配置,這里有點控制反轉的味道。

spring boot中由SpringFactoriesLoader這個類負責加載spring factories。下面分析下其原理:

SpringFactoriesLoader中有spring.factories的加載路徑,固定在類路徑下META-INF/spring.factories,其提供了以下幾種形式加載spring configration class

  • loadFactories,從META-INF/spring.factories中載入並實例化所給的類型
  • loadFactoryNames,根據被給類型的名稱從從META-INF/spring.factories中載入所給類的全限定名

其中具體載入細節,這里不再贅述,感興趣讀者可以閱讀源碼。主要是利用spring resource實現。


三.自動配置的關鍵注解系列

這節主要介紹開啟自動配置和輔助自動配置的系列注解,以及它們每個的具體作用和用法。不過在具體介紹其之前,讓我們先來看下spring中的另一套系列注解,這套系列注解和spring boot開啟自動配置的注解同宗同源。

在spring中有一套Enable類型的注解,這套Enables注解都是用於開啟spring應用某項功能,換而言之,就是將XML的配置形式以Java的形式展示

以上的這些Enable系注解都是告訴spring,讓其配置基礎Bean。讓應該開發者更加關注業務,而無需深入的關注逐項配置,加速開發。

但是這些Enable系注解的作用原理是什么?

Enable系列注解開啟spring某項功能的關鍵在於使用了@Import注解,每個@Enable注解的定義時都使用了@Import。

@Import注解的作用是將@Configuration、實現了ImportSelector或者ImportBeanDefinitionRegistrar接口的類、甚至規則的@Component的注解的注釋類導入。這里關於Import類的原理過程在我的另一篇文章有詳述,這里不再精講。

@Enable注解通過@Import注解導入其特定功能的Bean,從而實現開啟spring的特定功能。

spring boot的自動配置功能正是Enable系的另一個spring boot中的@EnableAutoConfiguration注解作用:

可以看粗@EnableAutoConfiguration也是通過@Import導入輔助Bean,從而開啟spring boot的自動配置,下面就重點分析@EnableAutoConfiguration。


四.自動配置原理

@EnableAutoConfiguration中的@Import注解導入了EnableAutoConfigurationImportSelector,其實現了ImportSelector接口,spring的ConfigurationClassParser中在解析ConfigurationClass時會解析@Import注解,並執行ImportSelector的實現。下面重點分析EnableAutoConfigurationImportSelector的實現。

ImportSelector是spring提供導入Bean定義的擴展,需要導入配置時可以實現該接口:

其中selectImports方法返回被@Configuration注釋的類的名字,spring將會載入這些配置類並解析注冊Bean定義。

EnableAutoConfigurationImportSelector中的selectImports實現如下:

  1. 判斷是否開啟自動配置,如果未開啟,則直接返回空的String[]
  2. 使用SpringFacotriesLoader從類路徑上的META-INF/spring.factories中載入所有的org.springframework.boot.autoconfigure.EnableAutoConfiguration
  3. 移除重復的Configuration
  4. 排序Configuration
  5. 返回這些Configuration

這里需要重點關注的是META-INF/spring.factories中載入所有的org.springframework.boot.autoconfigure.EnableAutoConfiguration中的內容是什么。這里以spring-boot-autoconfigure中的部分內容為例介紹:

從以上可以看出,org.springframework.boot.autoconfigure.EnableAutoConfiguration項是配置類的列表,selectImports會返回這些列表,交給spring將這些配置類載入,然后解析注冊成Bean Definition。由此,當@EnableAutoConfiguration開啟后,spring-boot在啟動時會載入類路徑上的這些@Configuration的配置類,從而完成自動配置。

自動配置的原理用一段話總結下:

spring boot中預內置了大量配置類,其實就是將平時傳統的spring應用的XML配置或者Java Config配置預先編排好,形成配置類放在spring-boot-autoconfigure項目中,當spring boot啟動時就會載入這些預先編排的配置類。當然載入時還會根據各種條件決定是否載入,如@Conditional系注解就派上用場,其決定org.springframework.boot.autoconfigure.EnableAutoConfiguration中的哪些配置或者Bean定義被載入!


五.自動配置實例分析

本節將以自動配置實例來加深對自動配置原理的理解。這里對mybatis-spring-boot-autoconfigure分析:

首先看下spring.factories文件內容:

可見EnableAutoConfiguration項是mybatis的spring配置類,當spring boot啟動時通過EnableAutoConfigurationImportSelector載入該配置類,解析注冊成Bean定義。

眾所周知,在日常項目開發中,使用mybatis和spring項目時,必須要配置的是SqlSessionFactory、SqlSessionTemplate這些mybatis的基礎Bean,並且制定mapper的掃描目錄等等屬性。

再來分析下這個mybatis的配置類主要配置了哪些內容:

因為MybatisAutoConfiguration類被@Configuration注解修飾,所以是Spring的Java配置類,spring會解析該配置類中的@Bean修飾的方法,生成bean。從其中的配置可以看出,mybatis的關鍵注解SqlSessionFactory、SqlSessionTemplate都被注冊成Bean。且使用了@Conditional系注解。當MapperFactoryBean不存在時,再使用@Import注解導入AutoConfiguredMapperScannerRegistrar,用於注冊被@Mapper注解修飾的mybatis的mapper接口為代理bean:

從以上的mybatis-spring-boot-autoconfigure配置中更深入的學習了spring boot自動配置的原理,就是將以前傳統的spring應用中需要開發者配編寫的大量spring配置交給了spring boot自己配置,從而簡化開發,簡化項目,實現敏捷快速開發的一種有效方式。

其中還兩個關鍵點需要注意的是:

@EnableConfigurationProperties注解也是Enable系注解之一,它是支持@ConfigurationProperties注解而生,它能夠快速的注冊被@ConfigurationProperties注釋的類為spring bean。

一般項目不會直接引用自動配置工程,而是通過引用starter從而傳遞依賴相應的自動配置。自動配置分為兩類:

  1. spring boot內置
  2. 非spring boot內置的(第三方開發、公司內部開發)

但是這些都是分為兩個項目:starter和autoconfigure,如spring-boot-autoconfigure被spring-boot-starter依賴,mybatis-spring-boot-autoconfigure被mybatis-spring-boot-starter依賴。從而形成starter模塊化,項目只需要依賴相應的starter便可以實現自動配置。


六.創建自己的Starter和自動配置

一般實現自動配置時,spring boot提出了規范。項目命名為 xxx-xxx-autoconfigure,其中目錄結構為:

其中spring.factories是自動配置的配置類,其中配置了自動配置類、spring boot監聽器類等等。
spring-configuration-metadata.json中配置了spring自動配置用到的屬性以及屬性的常用值,用於一些IDE在編寫application.propertie或者application.yml時能夠快捷的提示。

有了以上的原理和規范,實現自己需求的starter和自動配置就非常簡單。這里可以實現netty-spring-boot-starter和netty-spring-boot-autoconfigure。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM