<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          文末送書 | 帶你搞定 Spring Boot 核心運(yùn)行原理

          共 8014字,需瀏覽 17分鐘

           ·

          2020-08-06 14:32












          前言

          Spring Boot 最核心的功能就是“自動(dòng)配置”,這一切都基于“約定優(yōu)于配置”的原則。那么 Spring Boot 是如何約定,又是如何實(shí)現(xiàn)自動(dòng)配置功能的呢?

          下面帶大家來通過源碼學(xué)習(xí) Spring Boot 的核心運(yùn)作原理以及最核心的注解 @EnableAutoConfiguration 來進(jìn)行講解。

          1.1 核心運(yùn)行原理

          使用 Spring Boot 時(shí)我們只需引入對應(yīng)的 Starters,Spring Boot 啟動(dòng)時(shí)便自會(huì)動(dòng)加載相關(guān)依賴,配置相應(yīng)的初始化參數(shù),以最快捷、簡單的形式對第三方軟件進(jìn)行集成,這便是 Spring Boot 的自動(dòng)配置功能。先從整體上看一下 Spring Boot 實(shí)現(xiàn)該運(yùn)作機(jī)制涉及到的核心部分,如下圖。

          Spring Boot 核心運(yùn)行原理

          圖中描述了 Spring Boot 自動(dòng)配置運(yùn)作過程中涉及的幾個(gè)核心功能及其相互之間的關(guān)系。

          它們包括:@EnableAutoConfigurationspring.factories、各組件對應(yīng)的 AutoConfiguration 類、@Conditional 注解以及各種 Starters

          如果用一句話來描述整個(gè)過程就是:Spring Boot 通過 @EnableAutoConfiguration 注解開啟自動(dòng)配置,加載 spring.factories 中注冊的各種 AutoConfiguration 類,當(dāng)某個(gè) AutoConfiguration 類滿足其注解 @Conditional 指定的生效條件(Starters 提供的依賴、配置或 Spring 容器中是否存在某個(gè) Bean 等)時(shí),那么實(shí)例化該 AutoConfiguration 類中定義的 Bean(組件等),并注入 Spring 容器,至此就完成了依賴框架的自動(dòng)配置。

          先從概念及功能上了解一下上圖所屬部分的作用及相互關(guān)系。

          @EnableAutoConfiguration:該注解由組合注解 @SpringBootApplication 引入,完成自動(dòng)配置開啟,掃描各個(gè)jar包下的 spring.factories 文件,并加載其中注冊的 AutoConfiguration 類等。

          spring.factories:配置文件,位于 jar 包的META-INF目錄下,按照指定格式注冊了自動(dòng)配置的 AutoConfiguration 類,也可以包含其他類型待注冊的類。該配置文件不僅存在于 Spring Boot 項(xiàng)目中,也可以存在于自定義的自動(dòng)配置(或Starter)項(xiàng)目中。

          AutoConfiguration 類:自動(dòng)配置類,代表了 Spring Boot 中一類以XXAutoConfiguration命名的自動(dòng)配置類,其中定義了三方組件集成 Spring 所需初始化的 Bean 和條件。

          @Conditional:條件注解及其衍生注解,使用在 AutoConfiguration 類上,當(dāng)滿足該條件注解時(shí)才會(huì)實(shí)例化AutoConfiguration類。

          Starters:三方組件的依賴及配置,Spring Boot 已經(jīng)預(yù)置的組件。Spring Boot 默認(rèn)的 Starters 項(xiàng)目往往是只包含了一個(gè)pom依賴的項(xiàng)目。如果自定義的 starter,該項(xiàng)目還需包含spring.factories文件、AutoConfiguration類和其他配置類。

          以上在概念層面了解了 Spring Boot 自動(dòng)配置的整體流程和基本運(yùn)作原理,下面重點(diǎn)看一下 @EnableAutoConfiguration注解的功能。

          1.2 運(yùn)作原理源碼解析之 @EnableAutoConfiguration

          @EnableAutoConfiguration 是開啟自動(dòng)配置的注解,在創(chuàng)建的 Spring Boot 項(xiàng)目中并不能直接看到此注解,它是由組合注解@SpringBootApplication引入。下面,我們首先了解一下入口類和@SpringBootApplication注解,然后再深入了解@EnableAutoConfiguration注解的構(gòu)成與作用。

          1.2.1入口類和 @SpringBootApplication注解

          Spring Boot 項(xiàng)目創(chuàng)建完成會(huì)默認(rèn)生成一個(gè)*Application的入口類。默認(rèn)情況下,無論通過 IDEA 或通過官網(wǎng)創(chuàng)建基于 Maven 的 Spring Boot 項(xiàng)目,入口類的命名規(guī)則為:artifactId+Application。通過該類的 main 方法即可啟動(dòng) Spring Boot 項(xiàng)目。

          @SpringBootApplication
          public?class?SpringLearnApplication?{
          ?public?static?void?main(String[]?args)?{
          ??????SpringApplication.run(DemoApplication.class,?args);
          ???}
          }

          關(guān)于 main 方法并無特別之處,就是一個(gè)標(biāo)準(zhǔn)的 Java 應(yīng)用的 main 方法,這里是啟動(dòng) Spring Boot 項(xiàng)目的入口。默認(rèn)情況下,按照上述命名規(guī)則并包含 main 方法的類,我們以下稱作“入口類”。

          在入口類中,我們可以看到 Spring Boot 創(chuàng)建的代碼中(除單元測試外)唯一的一個(gè)注解就是@SpringBootApplication。它是 Spring Boot 項(xiàng)目的核心注解,用于開啟自動(dòng)配置,準(zhǔn)確說是該注解內(nèi)組合的@EnableAutoConfiguration開啟了自動(dòng)配置。

          @SpringBootApplication部分源代碼如下:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Inherited
          @SpringBootConfiguration
          @EnableAutoConfiguration
          @ComponentScan(excludeFilters?=?{
          ??????@Filter(type?=?FilterType.CUSTOM,?classes?=?TypeExcludeFilter.class),
          ??????@Filter(type?=?FilterType.CUSTOM,
          ????????????classes?=?AutoConfigurationExcludeFilter.class)?})
          public?@interface?SpringBootApplication?{
          ???//?排除指定自動(dòng)配置類
          ???@AliasFor(annotation?=?EnableAutoConfiguration.class)
          ???Class[]?exclude()?default?{};

          //?排除指定自動(dòng)配置類名
          ???@AliasFor(annotation?=?EnableAutoConfiguration.class)
          ???String[]?excludeName()?default?{};

          //?指定掃描的基礎(chǔ)包,激活注解組件的初始化
          ???@AliasFor(annotation?=?ComponentScan.class,?attribute?=?"basePackages")
          ???String[]?scanBasePackages()?default?{};

          //?指定掃描的類,用于初始化
          ???@AliasFor(annotation?=?ComponentScan.class,?attribute?=?"basePackageClasses")
          ???Class[]?scanBasePackageClasses()?default?{};

          //?指定是否代理@Bean方法以強(qiáng)制執(zhí)行bean的聲明周期行為。
          @AliasFor(annotation?=?Configuration.class)
          boolean?proxyBeanMethods()?default?true;
          }

          通過源代碼可以看出,該注解提供了以下成員屬性(注解中的成員變量以方法的形式體現(xiàn)):

          exclude:根據(jù)類(Class)排除指定的自動(dòng)配置,該成員屬性覆蓋了@SpringBootApplication 中組合的@EnableAutoConfiguration中定義的exclude成員屬性。

          excludeName:根據(jù)類名排除指定的自動(dòng)配置,同樣覆蓋了@EnableAutoConfiguration中的excludeName的成員屬性。

          scanBasePackages:指定掃描的基礎(chǔ) package,用于激活@Component等注解類的初始化。

          scanBasePackageClasses:掃描指定的類,用于組件的初始化。

          proxyBeanMethods:指定是否代理@Bean方法以強(qiáng)制執(zhí)行 bean 的聲明周期行為。此功能需要通過運(yùn)行時(shí)生成CGLIB子類來實(shí)現(xiàn)方法攔截,該子類有一定的限制,比如配置類及其方法不允許聲明為 final 等。默認(rèn)值為true,允許配置類中進(jìn)行“inter-bean references”(bean之間的引用)以及對該配置的@Bean方法的外部調(diào)用。如果@Bean方法都是自包含的,并且僅提供了容器使用的普通工程方法的功能,則可設(shè)置為false,避免處理CGLIB子類。Spring Boot 2.2新增該成員屬性,自動(dòng)配置類中基本都會(huì)使用,一般情況下都配置為false。

          以上源代碼會(huì)發(fā)現(xiàn),大量使用了@AliasFor注解,該注解用于橋接到其他注解,該注解的屬性中指定了所橋接的注解類。如果點(diǎn)進(jìn)去查看,會(huì)發(fā)現(xiàn)@SpringBootApplication定義的屬性,在其他注解中已經(jīng)定義過了。之所以使用@AliasFor注解并重新在@SpringBootApplication中定義,更多的意義是為了減少用戶使用多注解帶來的麻煩。

          @SpringBootApplication注解中組合了@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan。因此,在實(shí)踐過程中也可以使用這三個(gè)注解來替代@SpringBootApplication

          在早期版本中并沒有@SpringBootConfiguration注解,后新增了@SpringBootConfiguration并在其內(nèi)組合了@Configuration@EnableAutoConfiguration注解組合了@AutoConfigurationPackage。忽略掉一些基礎(chǔ)注解和元注解,@SpringBootApplication注解的組合結(jié)構(gòu)可以參考下圖。

          @SpringBootApplication注解組合結(jié)構(gòu)

          在上圖中,@SpringBootApplication除了組合元注解之外,核心包括:用于激活Spring Boot自動(dòng)配置的@EnableAutoConfiguration、用于激活@Component掃描的@ComponentScan、用于激活配置類的@Configuration。其@ComponentScan注解和@Configuration注解在Spring的日常使用中經(jīng)常用到,不再贅述,而關(guān)于@EnableAutoConfiguration正是我們下面要詳細(xì)介紹的。

          1.2.2 注解@EnableAutoConfiguration功能解析

          在未使用Spring Boot的情況下,Bean的生命周期由Spring來管理,然而Spring無法自動(dòng)配置@Configuration注解的類。而Spring Boot所做的核心之一就是根據(jù)約定可以自動(dòng)化的管理該注解標(biāo)注的類。用來實(shí)現(xiàn)該功能的組件之一便是@EnableAutoConfiguration注解。

          @EnableAutoConfiguration位于spring-boot-autoconfigure包內(nèi),當(dāng)使用@SpringBootApplication注解時(shí),該注解會(huì)自動(dòng)生效。

          @EnableAutoConfiguration的主要功能是啟動(dòng)Spring應(yīng)用程序上下文時(shí)進(jìn)行自動(dòng)配置,它會(huì)嘗試猜測并配置你可能需要的Bean。自動(dòng)配置通常是基于項(xiàng)目classpath中引入的類和已定義的Bean來實(shí)現(xiàn)的。在此過程中,被自動(dòng)配置的組件來自項(xiàng)目自身和項(xiàng)目依賴的jar包中。

          舉個(gè)例子:如果將tomcat-embedded.jar添加到classpath下,那么@EnableAutoConfiguration會(huì)認(rèn)為你準(zhǔn)備使用TomcatServletWebServerFactory類,并幫你初始化相關(guān)配置。與此同時(shí)如果自定義了基于ServletWebServerFactory的 Bean,那么,它將不會(huì)進(jìn)行TomcatServletWebServerFactory類的初始化。這一系列的操作判斷,都由 Spring Boot 來完成。

          下面我們來看一下@EnableAutoConfiguration注解的源代碼:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          @Inherited
          @AutoConfigurationPackage
          @Import(AutoConfigurationImportSelector.class)
          public?@interface?EnableAutoConfiguration?{
          //?用來覆蓋配置來開啟/關(guān)閉自動(dòng)配置的功能
          ???String?ENABLED_OVERRIDE_PROPERTY?=?"spring.boot.enableautoconfiguration";
          //?根據(jù)類(Class)排除指定的自動(dòng)配置
          ???Class[]?exclude()?default?{};
          //?根據(jù)類名排除指定的自動(dòng)配置
          ???String[]?excludeName()?default?{};
          }

          該注解提供了一個(gè)常量和兩個(gè)成員參數(shù)的定義:

          ENABLED_OVERRIDE_PROPERTY:可以用來覆蓋配置來開啟/關(guān)閉自動(dòng)配置的功能。

          exclude:根據(jù)類(Class)排除指定的自動(dòng)配置

          excludeName:根據(jù)類名排除指定的自動(dòng)配置。

          正如上面所說,@EnableAutoConfiguration會(huì)猜測你所需要使用的Bean,但如果在實(shí)戰(zhàn)中你并不需要它預(yù)置初始化的Bean,則可通過該注解的excludeexcludeName參數(shù)來進(jìn)行有針對性的排除。

          比如,當(dāng)不需要數(shù)據(jù)庫的自動(dòng)配置時(shí),可通過以下兩種方式讓其自動(dòng)配置失效:

          //?通過@SpringBootApplication排除DataSourceAutoConfiguration
          @SpringBootApplication(exclude?=?DataSourceAutoConfiguration.class)?
          public?class?SpringLearnApplication?{
          }

          或:

          //?通過@EnableAutoConfiguration排除DataSourceAutoConfiguration
          @Configuration
          @EnableAutoConfiguration(exclude?=?DataSourceAutoConfiguration.class)
          public?class?DemoConfiguration?{
          }

          需要注意的是,被@EnableAutoConfiguration注解的類所在 package 還具有特定的意義,通常會(huì)被作為掃描注解@Entity的根路徑。這也是為什么在使用@SpringBootApplication注解時(shí)需要將被注解的類放在頂級 package 下的原因,如果放在較低層級,則它所在 package 的同級或上級中的類則無法被掃描到。

          而對于入口類和其main方法來說,并不依賴@SpringBootApplication注解或@EnableAutoConfiguration,也就是說該注解可以使用在其他類上,而非入口類上,同樣生效。

          1.3 AutoConfigurationImportSelector源碼解析

          @EnableAutoConfiguration的關(guān)鍵功能是通過@Import注解導(dǎo)入的ImportSelector來完成的。從源碼得知@Import(AutoConfigurationImportSelector.class)@EnableAutoConfiguration注解的組成部分,也是自動(dòng)配置功能的核心實(shí)現(xiàn)者。

          它又可以分為兩部分:

          @Import和對應(yīng)的ImportSelector。本節(jié)重點(diǎn)講解@Import的基本使用和ImportSelector的實(shí)現(xiàn)類AutoConfigurationImportSelector

          1.3.3.AutoConfigurationImportSelector功能概述

          下面,通過一張流程圖來從整體上了解?AutoConfigurationImportSelector?功能及流程圖。

          圖中省略了外部通過@Import注解調(diào)用該類的部分。

          AutoConfigurationImportSelector核心功能及流程圖

          當(dāng)?AutoConfigurationImportSelector?被?@Import?注解引入之后,它的?selectImports?方法會(huì)被調(diào)用并執(zhí)行其實(shí)現(xiàn)的自動(dòng)裝配邏輯。讀者朋友需注意的?selectImports?方法幾乎涵蓋了組件自動(dòng)裝配的所有處理邏輯。

          通過上圖從整體上了解了?AutoConfigurationImportSelector?的概況及操作流程,關(guān)于?AutoConfigurationImportSelector?的詳細(xì)實(shí)現(xiàn)可參考Spring Boot中的源碼進(jìn)行逐步分析,本篇文章就不再進(jìn)行過多拓展。

          1.4 小結(jié)

          本篇文章圍繞 Spring Boot 的核心功能展開,帶大家從整體上了解 Spring Boot 自動(dòng)配置的原理以及自動(dòng)配置核心組件的運(yùn)作過程。只有掌握了這些基礎(chǔ)的組建及其功能,在后續(xù)集成其他三方類庫的自動(dòng)配置時(shí)才能夠更加清晰的了解它們都運(yùn)用了自動(dòng)配置的哪些功能。

          以上摘自朱智勝《Spring Boot技術(shù)內(nèi)幕——架構(gòu)設(shè)計(jì)與實(shí)現(xiàn)原理》。


          送書福利!!

          為了感謝大家一直以來對武培軒的支持,此次我準(zhǔn)備了3本《Spring Boot技術(shù)內(nèi)幕——架構(gòu)設(shè)計(jì)與實(shí)現(xiàn)原理》送給大家~



          參與方式


          ?方式一:公眾號【武培軒】回復(fù)【送書】,贈(zèng)書兩本

          ?方式二:到截止日期為止,分享榜第一名,贈(zèng)書一本

          特別提醒:方式一、二可同時(shí)參與(獲獎(jiǎng)幾率更大~),活動(dòng)截止日期8月12日下午6點(diǎn)


          獲獎(jiǎng)公布


          公布時(shí)間:8月13日次條

          特別提醒:兌獎(jiǎng)截止至8月20日,請參與讀者及時(shí)兌獎(jiǎng)


          ? ? ? ?
          ???
          Spring Boot 集成 Redis 實(shí)現(xiàn)數(shù)據(jù)緩存
          讀 Spring 源碼,我們可以從第一行讀起
          30 張圖手把手教你玩轉(zhuǎn) Spring 編譯

          覺得不錯(cuò),點(diǎn)個(gè)在看~

          瀏覽 55
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99精品欧美一区二区蜜桃免费 | 户外一区二区骚屄 | A一级黄色 | 久久视频免费在线观看 | 国产日韩视频在线观看 |