自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解 Spring Boot 自動配置原理和應用

開發(fā) 前端
我們詳細闡述了 Spring Boot 自動配置機制的實現(xiàn)原理,從源碼角度分析了為什么 Spring Boot 能夠做到自動配置,并結(jié)合 MyBatis 框架分析了它在開源框架中的具體應用。

我們知道,基于 Spring Boot,開發(fā)人員只需要在類路徑中引入一組第三方框架的 starter 組件,就能在 Spring 容器中使用這些框架所提供的各項功能。這在當下的開發(fā)過程中已是常態(tài),但在 Spring Boot 還沒有誕生之前卻是不可想象的。如果我們使用傳統(tǒng)的 Spring 框架,那就需要添加各種繁雜的配置信息才能啟動容器。那么,Spring Boot 是通過什么樣的機制來做到這一點的呢?這就是今天我們要討論的內(nèi)容——Spring Boot 的自動配置機制。

可以說,Spring Boot 的自動配置機制應用非常廣泛。在目前主流的開源框架中,都提供了各自的 starter 組件。例如,MyBatis 的 starter 組件為 mybatis-spring-boot-starter。而從擴展性上講,這也是 Spring Boot 為開發(fā)人員提供的一整套擴展機制,我們可以基于這套擴展機制實現(xiàn)自定義的 starter 組件。

Spring Boot 自動配置機制原理

Spring Boot 的自動配置功能非常強大,但也有一定的復雜度,讓我們先來深入理解其背后的實現(xiàn)原理。

@EnableAutoConfiguration 注解

我們通過查看@SpringBootApplication 注解的定義,發(fā)現(xiàn)該注解實際上是一個復合注解,由@SpringBootConfiguration、@ComponentScan 和@EnableAutoConfiguration 這三個獨立注解所組成。

圖 1 @SpringBootApplication 注解的組成結(jié)構(gòu)圖 1 @SpringBootApplication 注解的組成結(jié)構(gòu)

我們知道@ComponentScan 是傳統(tǒng) Spring 框架中對內(nèi)置的注解,而@SpringBootConfiguration 注解也很簡單,實際上只是對 Spring 框架中另一個常用注解@Configuration 的一種包裝,本身沒有定義任何內(nèi)容。所以,我們接下來重點剖析@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 {};
}

可以看到,這里出現(xiàn)了一個新的注解,即@AutoConfigurationPackage。從命名上講, @AutoConfigurationPackage 注解的作用就是自動對某一個代碼包進行配置。

另一方面,我們還看到這里通過@Import 注解引入了一個 AutoConfigurationImportSelector 類。從命名上,我們也不難理解該類的作用是完成對導入的配置信息的自動選擇。AutoConfigurationImportSelector 類的核心方法 getCandidateConfigurations 實現(xiàn)了這一目標。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
       List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
       …
       return configurations;
}

這里引出了在 Spring Boot 中真正負責加載配置信息的 SpringFactoriesLoader 類。這些類之間的交互關系如圖 2 所示:

圖 2 AutoConfigurationImportSelector 類層結(jié)構(gòu)圖圖 2 AutoConfigurationImportSelector 類層結(jié)構(gòu)圖

顯然,想要完成配置信息的自動選擇,我們首先需要執(zhí)行配置文件的加載操作,這部分功能是由 SpringFactoriesLoader 來完成的。SpringFactoriesLoader 也是 Spring Boot 自動配置得以實現(xiàn)的關鍵組件,我們來一起看一下。

SpringFactoriesLoader

SpringFactoriesLoader 類似 JDK 實現(xiàn) SPI 機制時所使用的 ServiceLoader 類,區(qū)別只是配置文件的存放位置和配置項對應的鍵值定義不同。在 SpringFactoriesLoader 中,我們需要通過 META-INF/spring.factories 文件目錄,來獲取服務定義文件,并通過 EnableAutoConfiguration 這個配置鍵來獲取具體的配置信息。圖 3 展示了 SpringFactoriesLoader 和 ServiceLoader 之間的區(qū)別。

圖 3 SpringFactoriesLoader 和 ServiceLoader 區(qū)別示意圖圖 3 SpringFactoriesLoader 和 ServiceLoader 區(qū)別示意圖

圖 3 SpringFactoriesLoader 和 ServiceLoader 區(qū)別示意圖

SpringFactoriesLoader 基于圖 3 指定的配置文件名和配置鍵獲取對應的配置信息,然后基于這些配置信息來實例化配置類,這里 Spring Boot 用到的是反射機制。SpringFactoriesLoader 類中的 loadSpringFactories 方法展示了這一過程。

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
       //從緩存中獲取配置內(nèi)容,如果存在則直接返回
       try {
              //基于 ClassLoader 從 META-INF/spring.factories 獲取配置文件資源地址 URL
              while (urls.hasMoreElements()) {
                     //獲取配置文件資源,加載配置項
                     for (Map.Entry<?, ?> entry : properties.entrySet()) {
                     //組裝配置項 Key-Value
                     }
              }
              //把配置信息放入緩存
              //返回結(jié)果
       }
}

同時,我們在 spring-boot-autoconfigure 工程的 spring.factories 配置文件中找到了如下所示配置項。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoCnotallow=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
…

可以看到,EnableAutoConfiguration 配置項中,定義了各種以-AutoConfiguration 結(jié)尾的配置類。通過 SpringFactoriesLoader,Spring Boot 就能做到在服務啟動的時候把它們加載到容器中并實現(xiàn)自動化配置。

MyBatis Spring Boot Starter

介紹完 Spring Boot 中應用程序的自動配置機制之后,我們來做一些實踐,通過剖析 MyBatis Spring Boot Starter 的啟動過程來加深對內(nèi)容的理解。

在 mybatis-spring-boot-starter 中存在幾個代碼工程,我們重點關注 mybatis-spring-boot-autoconfigure 工程。而在這個代碼工程中,最重要的顯然就是 MybatisAutoConfiguration 類。對于 Spring Boot 中的 AutoConfiguration 類,我們首先需要重點關注的是類定義上的注解。

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {

我們看到這里用到了@ConditionalOnClass 和@ConditionalOnSingleCandidate 這兩個注解,它們就是 Spring Boot 中的條件注解。在介紹 MybatisAutoConfiguration 之前,有必要對這些注解做一定展開。

@ConditionalOn 系列條件注解

我們在前面的內(nèi)容中已經(jīng)了解到以-AutoConfiguration 結(jié)尾的自動配置類數(shù)量會很多,在一個應用程序的開發(fā)過程中,我們通常不會全部用到它們。這時候就需要引入一種機制來對這些自動配置類進行過濾。為此,Spring Boot 提供了一組@ConditionalOn 系列條件注解。通過這些注解,我們就可以基于特定的條件有選擇性地加載某些配置類。在 Spring Boot 中常見的條件注解可以參考圖 4。

圖 4 常見@ConditionalOn 系列注解及其作用圖 4 常見@ConditionalOn 系列注解及其作用

在前面介紹的 MybatisAutoConfiguration 類的時候,出現(xiàn)了@ConditionalOnClass 和@ConditionalOnSingleCandidate 這兩個條件注解。基于這兩個條件注解,我們可以明確 MybatisAutoConfiguration 能夠?qū)嵗那疤嵊袃蓚€:一是類路徑中存在 SqlSessionFactory 和 SqlSessionFactoryBean;另一個則是容器中只存在一個 DataSource 實例。兩者缺一不可,這是一種常用的自動配置控制技巧。

然后,我們在 MybatisAutoConfiguration 類上看到了一個@EnableConfigurationProperties 注解。通過這個注解,所有添加了@ConfigurationProperties 注解的配置類就會自動生效。這里的@EnableConfigurationProperties 注解中指定的是 MybatisProperties 類,該類定義了 MyBatis 運行時所需要的各種配置信息,而我們在 MybatisProperties 類上確實也發(fā)現(xiàn)了@ConfigurationProperties 注解,并設置了 prefix 為“mybatis”。

@ConfigurationProperties(
     prefix = "mybatis"
)
public class MybatisProperties {
       ...
}

最后,在 MybatisAutoConfiguration 類上還存在一個@AutoConfigureAfter 注解,這個注解可以根據(jù)字面意思進行理解,即在完成某一個類的自動配置之后再執(zhí)行當前類的自動配置。這個需要提前裝配的類指的就是 DataSourceAutoConfiguration。

MybatisAutoConfiguration

理解了@ConditionalOnXXX、@EnableConfigurationProperties 和@AutoConfigureAfter 等一系列注解之后,我們回過頭來再看 MybatisAutoConfiguration 類的代碼結(jié)構(gòu)就顯得比較簡單了。MybatisAutoConfiguration 類中的一個核心方法就是如下所示的 sqlSessionFactory 方法。

@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
    factory.setDataSource(dataSource);
    factory.setVfs(SpringBootVFS.class);
    if (StringUtils.hasText(this.properties.getConfigLocation())) {
      factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
    }
    applyConfiguration(factory);
    //省略一系列配置項設置方法
    return factory.getObject();
}

顯然,這里基于前面介紹的 SqlSessionFactoryBean 構(gòu)建了 SqlSessionFactory 實例。注意到在該方法上同樣添加了一個@ConditionalOnMissingBean 注解,標明只有在當前上下文中不存在 SqlSessionFactoryBean 對象時才會執(zhí)行上述方法。

同樣,添加了@ConditionalOnMissingBean 注解的,還有如下所示的 sqlSessionTemplate 方法。

@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
    ExecutorType executorType = this.properties.getExecutorType();
    if (executorType != null) {
      return new SqlSessionTemplate(sqlSessionFactory, executorType);
    } else {
      return new SqlSessionTemplate(sqlSessionFactory);
    }
}

該方法用于構(gòu)建一個 SqlSessionTemplate 對象實例。在 MyBatis 中,SqlSessionTemplate 實現(xiàn)了 SqlSession 接口,相當于是全局唯一的 SqlSession 實例。

接下來,我們需要在 META-INF/spring.factories 文件中明確所指定的自動配置類。根據(jù) Spring Boot 自動配置機制的原理,對于 mybatis-spring-boot-autoconfigure 工程而言,這個配置項內(nèi)容應該如下所示。

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoCnotallow=\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

至此,整個 MyBatis Spring Boot Starter 的介紹就告一段落。作為總結(jié),我們可以把創(chuàng)建一個 Spring Boot Starter 的過程抽象成三個步驟。

圖 5 創(chuàng)建 Spring Boot Starter 的三個步驟圖 5 創(chuàng)建 Spring Boot Starter 的三個步驟

在日常開發(fā)過程中,我們就可以基于這三大步驟來實現(xiàn)一個自定義的 Spring Boot Starter。

總結(jié)

今天,我們詳細闡述了 Spring Boot 自動配置機制的實現(xiàn)原理,從源碼角度分析了為什么 Spring Boot 能夠做到自動配置,并結(jié)合 MyBatis 框架分析了它在開源框架中的具體應用。同時,我們在本講結(jié)尾部分還總結(jié)了開發(fā)一個 Spring Boot Starter 的三大步驟。實現(xiàn)一個自定義 Spring Boot Starter 也是日常開發(fā)的常見需求,我們在開發(fā)過程中可以基于本講的內(nèi)容加深對其實現(xiàn)原理的理解。

最后,我想給你留一道思考題:你能簡要描述實現(xiàn)一個自定義 Spring Boot Starter 需要哪些開發(fā)步驟嗎?

責任編輯:武曉燕 來源: 程序猿技術(shù)充電站
相關推薦

2023-10-18 08:12:34

Spring自動配置

2021-08-06 08:04:14

Spring Boot自動配置

2024-12-25 16:01:01

2017-03-23 09:29:06

2021-02-11 08:08:09

Spring Boot配置架構(gòu)

2024-12-16 08:10:00

Spring開發(fā)

2025-03-25 10:00:00

Spring開發(fā)Java

2024-01-04 08:16:34

Spring國際化標準

2023-12-27 18:05:13

2017-04-26 11:00:34

Spring BootHelloWorld詳解

2024-04-23 14:13:38

開發(fā)配置文件

2020-07-08 13:46:27

ApacheTomcat配置

2019-09-03 15:36:58

ApacheTomcat配置

2017-09-20 09:46:38

Spring BootSpring Clou內(nèi)存

2025-02-28 08:14:53

2020-11-02 07:00:29

Spring Boo注解自動化

2025-02-13 07:45:26

APISpringHTTP

2017-06-26 08:47:05

Spring Boot自動化配置

2025-01-03 16:27:35

SpringBoot代碼打包

2024-08-13 08:41:18

點贊
收藏

51CTO技術(shù)棧公眾號