欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot實(shí)現(xiàn)自動(dòng)配置的示例代碼

 更新時(shí)間:2025年01月26日 08:29:02   作者:楠枬  
本文主要介紹了SpringBoot實(shí)現(xiàn)自動(dòng)配置的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

什么是自動(dòng)配置?

Spring Boot 的自動(dòng)配置:當(dāng) Spring 容器啟動(dòng)后,一些配置類、bean 對(duì)象等就自動(dòng)存入 Ioc 容器中,而不再需要我們手動(dòng)去聲明,從而簡(jiǎn)化了程序開發(fā)過程,省去了繁瑣的配置操作

也就是說(shuō),Spring Boot 的自動(dòng)配置,就是 SpinrgBoot 依賴 jar 包中的配置類以及 Bean 加載到 Spring Ioc 容器中的過程

在本篇文章中,我們主要學(xué)習(xí)一下兩個(gè)方面:

1. Spring 如何將對(duì)象加載到 Spring Ioc 容器中

2. SpringBoot 是如何進(jìn)行實(shí)現(xiàn)的

我們首先來(lái)看 Spring 是如何加載 Bean 的

Spring 加載 Bean

當(dāng)我們?cè)陧?xiàng)目中引入第三方的包時(shí),其實(shí)就是在該項(xiàng)目下引入第三方的代碼,我們通過在該項(xiàng)目下創(chuàng)建不同的目錄來(lái)模擬第三方代碼的引入:

當(dāng)前項(xiàng)目目錄為 com.example.springautoconfig,模擬第三方代碼文件在 com.example.autoconfig 目錄下 

第三方文件代碼:

@Component
public class AutoConfig {
    public void test() {
        System.out.println("test...");
    }
}

獲取 AutoConfig:

@SpringBootTest
class SpringAutoconfigApplicationTests {
    @Autowired
    private ApplicationContext context;
    @Test
    void contextLoads() {
        AutoConfig bean = context.getBean(AutoConfig.class);
        System.out.println(bean);
    }
}

運(yùn)行結(jié)果:

此時(shí)顯示沒有 com.example.autoconfig.AutoConfig 這個(gè)類型的 bean

為什么會(huì)報(bào)錯(cuò)呢?

Spring 使用 類注解(@Controller、@Service、@Repository、@Component、@Configuration) 和 @Bean 注解 幫助我們將 Bean 加載到 Spring Ioc 容器中時(shí),有一個(gè)前提:這些注解需要和 SpringBoot 啟動(dòng)類(@SpringBootApplication 標(biāo)注的類)在同一個(gè)目錄下

而在上述項(xiàng)目中,啟動(dòng)類所在目錄為  com.example.springautoconfig,而 AutoConfig 類位于 com.example.autoconfig 目錄下,因此,SpringBoot 并沒有掃描到

可是,當(dāng)我們引入第三方的 jar 包時(shí),第三方的 jar 代碼目錄也不在啟動(dòng)類的目錄下,那么,如何讓 Spring 幫我們管理這些 Bean 的呢?

我們可以通過指定路徑或引入的文件告訴 Spring,讓 Spring 進(jìn)行掃描

常見的實(shí)現(xiàn)方法有兩種:

1. @ComponentScan 組件掃描

2. @Import 導(dǎo)入

@ComponentScan

使用 @ComponentScan 注解,指定 Spring 掃描路徑:

@SpringBootApplication
@ComponentScan("com.example.autoconfig")
public class SpringAutoconfigApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringAutoconfigApplication.class, args);
    }
}

運(yùn)行程序并觀察結(jié)果:

 成功獲取到 AutoConfig bean

那么,Spring Boot 是否使用了這種方式呢?

顯然沒有。若 Spring Boot 采用這種方式,當(dāng)我們引入大量的第三方依賴,如 MyBatis、jackson 等時(shí),就需要在啟動(dòng)類上配置不同依賴需要掃描的包,非常繁瑣

@Import

@Import 導(dǎo)入主要有以下幾種形式:

1. 導(dǎo)入類

2. 導(dǎo)入 ImportSelector 接口的實(shí)現(xiàn)類

導(dǎo)入類

@Import(AutoConfig.class)
@SpringBootApplication
public class SpringAutoconfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringAutoconfigApplication.class, args);
    }

}

運(yùn)行程序,觀察結(jié)果:

成功獲取到 AutoConfig Bean

若在文件中有多個(gè)配置項(xiàng):

@Component
public class AutoConfig2 {
    public void test() {
        System.out.println("test...");
    }
}

此時(shí)就需要導(dǎo)入多個(gè)類:

@Import({AutoConfig.class, AutoConfig2.class})
@SpringBootApplication
public class SpringAutoconfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringAutoconfigApplication.class, args);
    }

}

顯而易見,這種方式也比較繁瑣,因此,Spring Boot 也沒有采用

導(dǎo)入 ImportSelector 接口的實(shí)現(xiàn)類

實(shí)現(xiàn) ImportSelector 接口:

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 返回需要導(dǎo)入的全限定類名
        return new String[]{"com.example.autoconfig.AutoConfig", "com.example.autoconfig.AutoConfig2"};
    }
}

導(dǎo)入:

@Import(MyImportSelector.class)
@SpringBootApplication
public class SpringAutoconfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringAutoconfigApplication.class, args);
    }

}

運(yùn)行程序,并觀察結(jié)果:

這種方式也可以導(dǎo)入第三方依賴提供的 Bean

但是,它們都有一個(gè)明顯的問題:使用者需要知道第三方依賴中有哪些 Bean 對(duì)象或配置類,若我們?cè)趯?dǎo)入過程中漏掉了一些 Bean,就可能會(huì)導(dǎo)致我們的項(xiàng)目出現(xiàn)問題

依賴中有哪些 Bean,使用時(shí)需要配置哪些 Bean,這些問題第三方依賴最為清楚,那么,能否由第三方依賴來(lái)做這些事情呢?

比較常見的方法是第三方依賴提供一個(gè)注解,而這個(gè)注解一般是以 @EnableXxx 開頭的注解,而注解中封裝的就是 @Import 注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
// 指定要導(dǎo)入哪些類
@Import(MyImportSelector.class)
public @interface EnableAutoConfig {
}

在啟動(dòng)類上使用第三方提供的注解:

@EnableAutoConfig
@SpringBootApplication
public class SpringAutoconfigApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringAutoconfigApplication.class, args);
    }

}

運(yùn)行并觀察結(jié)果:

可以看到,這種方式也可以導(dǎo)入第三方依賴提供的 Bean,且這種方式不需要使用方知道第三方依賴中有哪些 Bean 對(duì)象或配置類,而在 Spring Boot 中也是使用的這種方式

SpringBoot 原理分析

SpringBoot 是如何進(jìn)行實(shí)現(xiàn)的?讓我們從 SpringBoot 的啟動(dòng)類開始看:

由 @SpringBootApplication 標(biāo)注的類就是 SpringBoot 項(xiàng)目的啟動(dòng)類:

這個(gè)類與普通類的唯一區(qū)別就是 @SpringBootApplication 注解,這個(gè)注解也是 SpringBoot 實(shí)現(xiàn)自動(dòng)配置的核心

 @SpringBootApplication 是一個(gè)組合注解,注解中包含了:

1. 元注解:

 JDK 中提供了 4 個(gè) 標(biāo)準(zhǔn)的用來(lái)對(duì)注解類型進(jìn)行注解的注解類,稱之為 meta-annotation(元注解)

分別為:

@Retention:描述注解保留的時(shí)間范圍

@Target:描述注解的使用范圍

@Documented:描述在使用 javadoc 工具為類生成幫助文檔時(shí)是否保留其注解信息

@Inherited:使被其修飾的注解具有繼承性(若某個(gè)類使用了 @Inherited,則其子類將自動(dòng)具有該注解)

2. @SpringBootConfiguration:

 

標(biāo)識(shí)當(dāng)前類是一個(gè)配置類,里面其實(shí)就是 @Configuration,只是做了進(jìn)一步的封裝

其中,@Indexed 注解是用來(lái)加速應(yīng)用啟動(dòng)的

3. @EnableAutoConfiguration(開啟自動(dòng)配置)

是 spiring 自動(dòng)配置的核心注解,我們?cè)诤罄m(xù)詳細(xì)理解

4.  ComponentScan(包掃描)

可以通過 basePackageClasses 或 basePackages 來(lái)定義要掃描的特定包,若沒有定義特定的包,將從聲明該注解的類的包開始掃描,這也是 SpringBoot 項(xiàng)目聲明的注解類為什么必須在啟動(dòng)類目錄下

也可以自定義過濾器,用于排查一些類、注解等

接下來(lái),我們重點(diǎn)來(lái)看  @EnableAutoConfiguration(開啟自動(dòng)配置)

@EnableAutoConfiguration

 @EnableAutoConfiguration 中主要包含兩部分:

@Import(AutoConfigurationImportSelector.class) 

@AutoConfigurationPackage

我們先來(lái)看  @Import(AutoConfigurationImportSelector.class) 

@Import(AutoConfigurationImportSelector.class) 

使用 @Import 注解,導(dǎo)入了實(shí)現(xiàn) ImportSelector 接口的實(shí)現(xiàn)類:

在 selectImports() 方法中,調(diào)用了 getAutoConfigurationEntry() 方法,獲取可自動(dòng)配置的配置類信息

我們繼續(xù)看  getAutoConfigurationEntry() 方法:

在  getAutoConfigurationEntry() 方法中,主要通過 getCandidateConfigurations(annotationMetadata, attributes) 方法 和 fireAutoConfigurationImportEvents(configurations, exclusions) 方法,獲取在配置文件中配置的所有自動(dòng)配置類的集合

我們先看  getCandidateConfigurations(annotationMetadata, attributes) 方法:

在 getCandidateConfigurations(annotationMetadata, attributes) 方法中,使用 ImportCandidates 進(jìn)行加載

那么,從哪里進(jìn)行加載呢?

從 斷言 的錯(cuò)誤信息中我們可以找到答案:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

也就是說(shuō), getCandidateConfigurations 方法會(huì)獲取所有基于META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中配置類的集合

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件:

 其中包含了很多第三方依賴的配置文件 

我們以 redis 為例:

查看 RedisAutoConfiguration

可以看到,在使用 redis 時(shí)常用的 RedisTemplate 和 StringRedisTemplate 就位于其中,在我們需要使用時(shí)直接使用 @Autowired 進(jìn)行注入就可以了

但是,由于當(dāng)前項(xiàng)目并沒有引入 redis 相關(guān) jar 包,此時(shí)這個(gè)類并不能被加載

也就是說(shuō)在加載自動(dòng)配置類的時(shí)候,并不是將所有的配置全部加載進(jìn)來(lái),而是會(huì)先進(jìn)行判斷,根據(jù) @ConditionalOnMissingBean 、@ConditionalOnSingleCandidate 等注解的判斷進(jìn)行動(dòng)態(tài)加載

即,在配置文件中使用 @Bean 聲明對(duì)象,spring 會(huì)自動(dòng)調(diào)用配置類中使用 @Bean 標(biāo)識(shí)的方法,并將對(duì)象存放到 Spring Ioc 中,但是,在加載自動(dòng)配置類的時(shí)候,并不是將所有的配置全部加載進(jìn)來(lái),而是會(huì)通過 @Conditional 等注解的判斷進(jìn)行動(dòng)態(tài)加載@Conditional 是 spring 底層注解,會(huì)根據(jù)不同的條件,進(jìn)行條件判斷,若滿足指定條件,配置類中的配置才會(huì)生效)

我們繼續(xù)看 fireAutoConfigurationImportEvents 方法,找到是從哪里獲取配置類的:

可以看到,fireAutoConfigurationImportEvents 方法最終會(huì)從 META-INF/spring.factories 中獲取配置類的集合

我們來(lái)看 META-INF/spring.factories

META-INF/spring.factories 文件是 Spring 內(nèi)部提供的一個(gè)約定俗稱的加載方式,只需要在模塊的 META-INF/spring.factories 文件中進(jìn)行配置,Spring 就會(huì)把相應(yīng)的實(shí)現(xiàn)類注入到 Spring 容器中

例如,有一個(gè)自動(dòng)配置類,希望 SpringBoot 在啟動(dòng)時(shí)自動(dòng)加載這個(gè)配置,我們就可以在 META-INF/spring.factories 文件按照指定格式進(jìn)行配置,讓 Spring Boot 應(yīng)用啟動(dòng)時(shí),讀取這個(gè) spring.factories 文件,根據(jù)文件中指定的配置類來(lái)進(jìn)行自動(dòng)配置

spring 會(huì)加載所有 jar 包下的 META-INF/spring.factories 文件

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports   META-INF/spring.factories 都在引入的起步依賴中:

我們繼續(xù)看  AutoConfigurationPackage

AutoConfigurationPackage

在這個(gè)注解中,主要導(dǎo)入了一個(gè)配置文件 AutoConfigurationPackages.Registrar.class

我們繼續(xù)看 Registrar :

 Registrar 實(shí)現(xiàn)了 ImportBeanDefinitionRegistrar 接口,可以被 @Import 導(dǎo)入到 spring 容器中

new PackageImports(metadata).getPackageNames().toArray(new String[0]): 當(dāng)前啟動(dòng)類所在的包名

也就是說(shuō),@AutoConfigurationPackage 的作用是 將啟動(dòng)類所在的包下面所有的組件都掃描注冊(cè)到 spring 容器中

最后,我們來(lái)總結(jié)一下 SpringBoot 自動(dòng)配置的流程

SpringBoot 自動(dòng)配置流程

 SpringBoot 的自動(dòng)配置的入口是  @SpringBootApplication 注解,在這個(gè)注解中,主要封裝了 3 個(gè)注解:

@SpringBootConfiguration:標(biāo)識(shí)當(dāng)前類是配置類

@ComponentScan(包掃描):可以通過 basePackageClasses 或 basePackages 定義要掃描的特定包,若沒有定義特定的包,將從聲明該注解的類的包開始掃描,也就是說(shuō),默認(rèn)情況下掃描的是啟動(dòng)類所在的當(dāng)前包以及子包

@EnableAutoConfiguration(開啟自動(dòng)配置):主要包含兩部分:

@Import(AutoConfigurationImportSelector.class) :讀取 META-INF/spring.factories 和  META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中定義的配置類????

@AutoConfigurationPackage:將啟動(dòng)類所在的包下所有組件都注入到 Spring 容器中

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)自動(dòng)配置的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot自動(dòng)配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java源碼解析之超級(jí)接口Map

    Java源碼解析之超級(jí)接口Map

    今天給各位小伙伴介紹一下超級(jí)接口Map,文中對(duì)接口Map講的非常詳細(xì),對(duì)正在學(xué)習(xí)java的小伙伴們有很好的幫助喲,需要的朋友可以參考下
    2021-05-05
  • IDEA中Maven爆紅以及依賴下載失敗的最全解決方案

    IDEA中Maven爆紅以及依賴下載失敗的最全解決方案

    這篇文章主要介紹了IDEA中Maven爆紅,依賴下載失敗的最全解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • Java中this關(guān)鍵字的用法詳解

    Java中this關(guān)鍵字的用法詳解

    我知道很多朋友都和我一樣,在JAVA程序中似乎經(jīng)常見到this,自己也偶爾用到它,但是到底this該怎么用,卻心中無(wú)數(shù),下面這篇文章主要給大家介紹了關(guān)于Java中this關(guān)鍵字用法的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • Java?Deque基本概念和使用方法

    Java?Deque基本概念和使用方法

    Deque雙端隊(duì)列是Java?Collections?Framework的一部分,支持在兩端插入和刪除操作,它繼承自Queue接口,可以作為隊(duì)列FIFO或棧LIFO使用,本文介紹java?Deque基本概念和使用方法,感興趣的朋友一起看看吧
    2025-03-03
  • springboot配置Hikari連接池方式

    springboot配置Hikari連接池方式

    本文介紹了在Springboot中配置Hikari連接池的具體參數(shù)和設(shè)置,涵蓋了autoCommit, connectionTimeout, idleTimeout, maxLifetime, minimumIdle, maximumPoolSize等關(guān)鍵配置項(xiàng),并提供了它們的默認(rèn)值、描述和條件下的重置規(guī)則
    2024-09-09
  • java位運(yùn)算加密示例

    java位運(yùn)算加密示例

    通過位運(yùn)算中的"^"異或運(yùn)算符把字符串與一個(gè)指定的值進(jìn)行異或運(yùn)算,從而改變字符串每個(gè)字符的值,這樣就可以得到一個(gè)加密后的字符串
    2014-02-02
  • Java調(diào)用瀏覽器打開網(wǎng)頁(yè)完整實(shí)例

    Java調(diào)用瀏覽器打開網(wǎng)頁(yè)完整實(shí)例

    這篇文章主要介紹了Java調(diào)用瀏覽器打開網(wǎng)頁(yè)的方法,以完整實(shí)例形式分析了java打開網(wǎng)頁(yè)的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • springboot?vue測(cè)試平臺(tái)開發(fā)調(diào)通前后端環(huán)境實(shí)現(xiàn)登錄

    springboot?vue測(cè)試平臺(tái)開發(fā)調(diào)通前后端環(huán)境實(shí)現(xiàn)登錄

    這篇文章主要介紹了springboot?vue測(cè)試平臺(tái)開發(fā)調(diào)通前后端環(huán)境實(shí)現(xiàn)登錄詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Java中final、static關(guān)鍵字與方法的重寫和繼承易錯(cuò)點(diǎn)整理

    Java中final、static關(guān)鍵字與方法的重寫和繼承易錯(cuò)點(diǎn)整理

    這篇文章主要給大家介紹了關(guān)于Java中final、static關(guān)鍵字與方法的重寫和繼承易錯(cuò)點(diǎn)的相關(guān)資料,在Java編程中final關(guān)鍵字用于限制方法或類的進(jìn)一步修改,final方法不能被子類重寫,而static方法不可被重寫,只能被遮蔽,需要的朋友可以參考下
    2024-10-10
  • Java獲取時(shí)間打印到控制臺(tái)代碼實(shí)例

    Java獲取時(shí)間打印到控制臺(tái)代碼實(shí)例

    這篇文章主要介紹了Java獲取時(shí)間打印到控制臺(tái)代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02

最新評(píng)論