<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核心原理實(shí)現(xiàn)及核心注解類(文末小送8本書)

          共 8385字,需瀏覽 17分鐘

           ·

          2020-07-31 17:37

          本文來源:搜狐技術(shù)產(chǎn)品;作者:朱智勝

          1.前言

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

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

          1-SpringBoot核心運(yùn)行原理

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

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

          先從概念及功能上了解一下上圖所屬部分的作用及相互關(guān)系,后面章節(jié)會(huì)針對(duì)每個(gè)功能及組件進(jìn)行源代碼級(jí)別的講解。

          1. @EnableAutoConfiguration?該注解由組合注解?@SpringBootApplication?引入,完成自動(dòng)配置開啟,掃描各個(gè) jar 包下的spring.factories文件,并加載其中注冊(cè)的?AutoConfiguration?類等。
          2. spring.factories?配置文件,位于 jar 包的 META-INF 目錄下,按照指定格式注冊(cè)了自動(dòng)配置的?AutoConfiguration?類,也可以包含其他類型待注冊(cè)的類。該配置文件不僅存在于 Spring Boot 項(xiàng)目中,也可以存在于自定義的自動(dòng)配置(或 Starter)項(xiàng)目中。
          3. AutoConfiguration?自動(dòng)配置類,代表了 Spring Boot 中一類以?XXAutoConfiguration?命名的自動(dòng)配置類。其中定義了三方組件集成 Spring 所需初始化的 Bean 和條件。
          4. @Conditional?條件注解及其衍生注解,使用在?AutoConfiguration?類上,當(dāng)滿足該條件注解時(shí)才會(huì)實(shí)例化?AutoConfiguration類?。
          5. 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è)?XXApplication?的入口類。默認(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)):

          1. exclude:根據(jù)類(Class)排除指定的自動(dòng)配置,該成員屬性覆蓋了?@SpringBootApplication?中組合的@EnableAutoConfiguration中定義的 exclude 成員屬性。
          2. excludeName:根據(jù)類名排除指定的自動(dòng)配置,同樣覆蓋了?@EnableAutoConfiguration?中的 excludeName 的成員屬性。
          3. scanBasePackages:指定掃描的基礎(chǔ) package,用于激活?@Component?等注解類的初始化。
          4. scanBasePackageClasses:掃描指定的類,用于組件的初始化。
          5. proxyBeanMethods:?指定是否代理?@Bean?方法以強(qiáng)制執(zhí)行 bean 的聲明周期行為。此功能需要通過運(yùn)行時(shí)生成 CGLIB 子類來實(shí)現(xiàn)方法攔截,該子類有一定的限制,比如配置類及其方法不允許聲明為 final 等。默認(rèn)值為 true,允許配置類中進(jìn)行“inter-bean references”(bean 之間的引用)以及對(duì)該配置的?@Bean?方法的外部調(diào)用。如果?@Bean?方法都是自包含的,并且僅提供了容器使用的普通工程方法的功能,則可設(shè)置為 false,避免處理 CGLIB 子類。Spring Boot 2.2 新增該成員屬性,后面章節(jié)涉及到的自動(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)可以參考下圖。

          2-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ù)的定義:

          1. ENABLED_OVERRIDE_PROPERTY:可以用來覆蓋配置來開啟/關(guān)閉自動(dòng)配置的功能。
          2. exclude:根據(jù)類(Class)排除指定的自動(dòng)配置
          3. excludeName:根據(jù)類名排除指定的自動(dòng)配置。

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

          比如,當(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í)需要將被注解的類放在頂級(jí) package 下的原因,如果放在較低層級(jí),則它所在 package 的同級(jí)或上級(jí)中的類則無法被掃描到。

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

          1.3.AutoConfigurationImportSelector 源碼解析

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

          它又可以分為兩部分:

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

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

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

          3-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)原理》

          √ 本書有別于市面上其他 Spring Boot 入門和實(shí)戰(zhàn)類的相關(guān)書,更多側(cè)重于 Spring Boot 設(shè)計(jì)思想、原理及具體功能實(shí)現(xiàn)的源代碼分析,從一個(gè)更深的層次帶領(lǐng)讀者了解 Spring Boot。書中內(nèi)容涵蓋范圍較廣,卻又不顯冗余,每一個(gè)知識(shí)點(diǎn)都通過典型的功能實(shí)現(xiàn)來進(jìn)行分析。

          √ 本書內(nèi)容基于 Spring Boot 2.2.1,書中涵蓋的許多知識(shí)點(diǎn)都是作者多年經(jīng)驗(yàn)的總結(jié),希望能給大家?guī)砣碌闹R(shí)盛宴。

          1.5.后記-送書福利

          為了感謝小伙伴們一直以來的支持,讓 Guide 這個(gè)菜逼寫的文章每天能被這么多優(yōu)秀的小伙伴看到,小送 8 本《Spring Boot 技術(shù)內(nèi)幕——架構(gòu)設(shè)計(jì)與實(shí)現(xiàn)原理》送給大家!

          參與方式 1:留言送 5 本(周五晚12點(diǎn)截止)

          留言聊一下下面這些話題其中的一個(gè)或者是其他和 SpringBoot 相關(guān)的話題:

          1. 自己對(duì)于 SpringBoot 和 Spring 有啥區(qū)別的理解?(SpringBoot為啥這么火??)
          2. 自己公司為啥還沒用上 SpringBoot ,有啥吐槽的?
          3. 自己是如何學(xué)習(xí) Spring Boot 的?

          參與方式 2:直接抽獎(jiǎng)送 3 本 (周五晚12點(diǎn)開獎(jiǎng))

          我是Guide哥,Java后端開發(fā),半個(gè)全棧,自由的少年。一個(gè)三觀比主角還正的技術(shù)人。我們下期再見!

          瀏覽 65
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  日本成人A电影院 | 水蜜桃在线观看视频 | 国产精品永久久久久久久WWW | 欧美三级高清在线 | 频逼特逼在线视频 |