偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

詳解 Spring Boot 自動(dòng)配置原理和應(yīng)用

開發(fā) 前端
我們?cè)敿?xì)闡述了 Spring Boot 自動(dòng)配置機(jī)制的實(shí)現(xiàn)原理,從源碼角度分析了為什么 Spring Boot 能夠做到自動(dòng)配置,并結(jié)合 MyBatis 框架分析了它在開源框架中的具體應(yīng)用。

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

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

Spring Boot 自動(dòng)配置機(jī)制原理

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

@EnableAutoConfiguration 注解

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

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

我們知道@ComponentScan 是傳統(tǒng) Spring 框架中對(duì)內(nèi)置的注解,而@SpringBootConfiguration 注解也很簡單,實(shí)際上只是對(duì) Spring 框架中另一個(gè)常用注解@Configuration 的一種包裝,本身沒有定義任何內(nèi)容。所以,我們接下來重點(diǎn)剖析@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)了一個(gè)新的注解,即@AutoConfigurationPackage。從命名上講, @AutoConfigurationPackage 注解的作用就是自動(dòng)對(duì)某一個(gè)代碼包進(jìn)行配置。

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

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

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

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

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

SpringFactoriesLoader

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

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

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

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

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

同時(shí),我們?cè)?spring-boot-autoconfigure 工程的 spring.factories 配置文件中找到了如下所示配置項(xiàng)。

# 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 配置項(xiàng)中,定義了各種以-AutoConfiguration 結(jié)尾的配置類。通過 SpringFactoriesLoader,Spring Boot 就能做到在服務(wù)啟動(dòng)的時(shí)候把它們加載到容器中并實(shí)現(xiàn)自動(dòng)化配置。

MyBatis Spring Boot Starter

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

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

@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 這兩個(gè)注解,它們就是 Spring Boot 中的條件注解。在介紹 MybatisAutoConfiguration 之前,有必要對(duì)這些注解做一定展開。

@ConditionalOn 系列條件注解

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

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

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

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

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

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

MybatisAutoConfiguration

理解了@ConditionalOnXXX、@EnableConfigurationProperties 和@AutoConfigureAfter 等一系列注解之后,我們回過頭來再看 MybatisAutoConfiguration 類的代碼結(jié)構(gòu)就顯得比較簡單了。MybatisAutoConfiguration 類中的一個(gè)核心方法就是如下所示的 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);
    //省略一系列配置項(xiàng)設(shè)置方法
    return factory.getObject();
}

顯然,這里基于前面介紹的 SqlSessionFactoryBean 構(gòu)建了 SqlSessionFactory 實(shí)例。注意到在該方法上同樣添加了一個(gè)@ConditionalOnMissingBean 注解,標(biāo)明只有在當(dāng)前上下文中不存在 SqlSessionFactoryBean 對(duì)象時(shí)才會(huì)執(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)建一個(gè) SqlSessionTemplate 對(duì)象實(shí)例。在 MyBatis 中,SqlSessionTemplate 實(shí)現(xiàn)了 SqlSession 接口,相當(dāng)于是全局唯一的 SqlSession 實(shí)例。

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

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

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

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

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

總結(jié)

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

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

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

2023-10-18 08:12:34

Spring自動(dòng)配置

2024-12-25 16:01:01

2021-08-06 08:04:14

Spring Boot自動(dòng)配置

2017-03-23 09:29:06

2021-02-11 08:08:09

Spring Boot配置架構(gòu)

2025-03-25 10:00:00

Spring開發(fā)Java

2024-01-04 08:16:34

Spring國際化標(biāo)準(zhǔn)

2023-12-27 18:05:13

2017-04-26 11:00:34

Spring BootHelloWorld詳解

2024-04-23 14:13:38

開發(fā)配置文件

2024-12-16 08:10:00

Spring開發(fā)

2019-09-03 15:36:58

ApacheTomcat配置

2020-07-08 13:46:27

ApacheTomcat配置

2017-09-20 09:46:38

Spring BootSpring Clou內(nèi)存

2025-02-28 08:14:53

2025-05-29 05:59:56

2020-11-02 07:00:29

Spring Boo注解自動(dòng)化

2024-11-21 14:42:31

2024-10-14 17:18:27

2025-01-15 08:19:12

SpringBootRedis開源
點(diǎn)贊
收藏

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