<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Spring Boot 啟動過程與自動配置詳解:從源碼到實現

      在使用 Spring Boot 時,開發者常常會感到驚訝:為什么這么少的配置卻能實現如此豐富的功能?為何啟動一個 Spring Boot 應用可以變得如此簡單便捷?在這個看似平凡的啟動過程中,其實隱藏著一套精妙的自動化機制和源碼邏輯。本文將帶你深入探索 Spring Boot 的啟動流程,逐步揭開自動配置的幕后奧秘。通過了解這些底層原理,你將發現,原來每一次應用的無縫啟動都是精心設計的結果,讓你對 Spring Boot 有更深刻的理解和掌控力!

      一、整體概述

      (一)基本整體初步分析

      Spring Boot 是一個用于構建獨立的、生產級的 Spring 應用程序的框架,它提供了自動化的配置和約定優于配置的原則。在理解 Spring Boot 的啟動配置原理之前,我們需要了解幾個關鍵概念。

      首先,Spring Boot 使用了基于約定的自動配置機制。它通過在 classpath 下查找特定的配置文件和類,根據應用程序所使用的依賴自動配置 Spring 應用程序的各種組件。這樣可以大大簡化開發者的工作,減少了手動配置的需求。

      其次,Spring Boot 使用了條件化配置(Conditional Configuration)的機制。這意味著配置的應用取決于一組條件是否滿足。條件可以基于多種因素,如 classpath 中存在特定的類、特定的 bean 是否存在等等。通過條件化配置,Spring Boot 可以根據不同的環境和需求進行動態的配置。

      Spring Boot 的啟動配置原理可以概括如下:

      1. 在啟動過程中,Spring Boot 會加載并解析應用程序的配置文件,其中包括 application.properties 或 application.yml 文件等。這些文件中可以定義各種屬性和配置信息,如數據庫連接、日志級別等。
      2. Spring Boot 會自動掃描 classpath 下的特定包,尋找帶有特定注解的類,如 @SpringBootApplication。這個注解標識了一個 Spring Boot 應用程序的入口點。
      3. 根據配置文件中的屬性和條件化配置的機制,Spring Boot 自動配置應用程序的各種組件,包括數據庫連接池、消息隊列、Web 服務器等。如果需要進行自定義配置,可以使用專門的注解或編寫自定義的配置類。
      4. 在應用程序啟動時,Spring Boot 會初始化 Spring 容器,并根據配置進行相應的初始化工作。這包括創建和管理 bean、處理依賴注入等。

      總的來說,Spring Boot 的啟動配置原理是基于自動化的約定和條件化配置機制。它通過讀取配置文件、掃描注解、自動配置組件等步驟,簡化了應用程序的配置過程,并提供了靈活性和易用性。

      (二)從啟動來看整體過程圖分析

      每個SpringBoot程序都有一個主入口main方法,main里面調用SpringApplication.run()啟動整個SpringBoot程序,該方法所在類需要使用@SpringBootApplication注解,例如如下

       
      1. package org.zyf.javabasic;
      2.  
      3. import org.springframework.boot.SpringApplication;
      4. import org.springframework.boot.autoconfigure.SpringBootApplication;
      5. import org.springframework.context.ApplicationContext;
      6. import org.springframework.context.annotation.ComponentScan;
      7. import org.springframework.context.annotation.EnableAspectJAutoProxy;
      8. import springfox.documentation.swagger2.annotations.EnableSwagger2;
      9.  
      10. /**
      11. * 描述:啟動入口類
      12. *
      13. * @author yanfengzhang
      14. * @date 2019-12-19 18:11
      15. */
      16. @SpringBootApplication
      17. @ComponentScan(basePackages = {"org.zyf.javabasic"})
      18. @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
      19. @EnableSwagger2
      20. public class ZYFApplication {
      21. public static void main(String[] args) {
      22. ApplicationContext context = SpringApplication.run(ZYFApplication.class, args);
      23. }
       

      其中對@SpringBootApplication進行展開分析:

       
      1. //
      2. // Source code recreated from a .class file by IntelliJ IDEA
      3. // (powered by FernFlower decompiler)
      4. //
      5.  
      6. package org.springframework.boot.autoconfigure;
      7.  
      8. import java.lang.annotation.Documented;
      9. import java.lang.annotation.ElementType;
      10. import java.lang.annotation.Inherited;
      11. import java.lang.annotation.Retention;
      12. import java.lang.annotation.RetentionPolicy;
      13. import java.lang.annotation.Target;
      14. import org.springframework.boot.SpringBootConfiguration;
      15. import org.springframework.boot.context.TypeExcludeFilter;
      16. import org.springframework.context.annotation.ComponentScan;
      17. import org.springframework.context.annotation.FilterType;
      18. import org.springframework.context.annotation.ComponentScan.Filter;
      19. import org.springframework.core.annotation.AliasFor;
      20.  
      21. @Target({ElementType.TYPE})
      22. @Retention(RetentionPolicy.RUNTIME)
      23. @Documented
      24. @Inherited
      25. @SpringBootConfiguration
      26. @EnableAutoConfiguration
      27. @ComponentScan(
      28. excludeFilters = {@Filter(
      29. type = FilterType.CUSTOM,
      30. classes = {TypeExcludeFilter.class}
      31. ), @Filter(
      32. type = FilterType.CUSTOM,
      33. classes = {AutoConfigurationExcludeFilter.class}
      34. )}
      35. )
      36. public @interface SpringBootApplication {
      37. @AliasFor(
      38. annotation = EnableAutoConfiguration.class
      39. )
      40. Class<?>[] exclude() default {};
      41.  
      42. @AliasFor(
      43. annotation = EnableAutoConfiguration.class
      44. )
      45. String[] excludeName() default {};
      46.  
      47. @AliasFor(
      48. annotation = ComponentScan.class,
      49. attribute = "basePackages"
      50. )
      51. String[] scanBasePackages() default {};
      52.  
      53. @AliasFor(
      54. annotation = ComponentScan.class,
      55. attribute = "basePackageClasses"
      56. )
      57. Class<?>[] scanBasePackageClasses() default {};
      58. }
       

      @SpringBootApplication包括三個注解,功能如下:

      • @SpringBootConfiguration(內部為@Configuration):被標注的類等于在spring的XML配置文件中(applicationContext.xml),裝配所有bean事務,提供了一個spring的上下文環境
      • @ComponentScan:組件掃描,可自動發現和裝配Bean(比如@Component和@Configuration),默認掃描SpringApplication的run方法里類所在的包路徑下所有文件
      • @EnableAutoConfiguration:激活SpringBoot自動裝配的特性

      現在對主入口main方法進行展開來給出整體的流程圖分析

      二、SpringApplication構造過程分析

      進入main里面的run方法,創建了一個SpringApplication實例,配置一些基本的環境變量、資源、構造器、監聽器,進入這個SpringApplication有參構造函數

       
      1. public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
      2. this.sources = new LinkedHashSet();
      3. this.bannerMode = Mode.CONSOLE;
      4. this.logStartupInfo = true;
      5. this.addCommandLineProperties = true;
      6. this.addConversionService = true;
      7. this.headless = true;
      8. this.registerShutdownHook = true;
      9. this.additionalProfiles = new HashSet();
      10. this.isCustomEnvironment = false;
      11. this.resourceLoader = resourceLoader;
      12. Assert.notNull(primarySources, "PrimarySources must not be null");
      13. this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
      14. this.webApplicationType = WebApplicationType.deduceFromClasspath();
      15. this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
      16. this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
      17. this.mainApplicationClass = this.deduceMainApplicationClass();
      18. }
       

      注意:在該構造方法內,做的工作就是把相關的類(主要是initializer和listener)加載進容器中,并沒有執行

      (一)驗證主配置類不為空并且保存主類

      (二)推斷項目的類型

      進入對應方法分析如下:

      推斷項目的類型可能為reactive、none、servlet三種類型,默認為servlet類型。其使用類加載器判斷類型的邏輯如下

      類型

      判斷情況

      reactive

      存在Spring WebFlux的DispatcherHandler存在,但是Spring MVC的DispatcherServlet不存在

      none

      二者都不存在

      servlet

      剩余所有情況

      (三)初始化initializers

      先進入ApplicationContextInitializer接口,這個接口只有一個方法initialize

       
      1. package org.springframework.context;
      2.  
      3. public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
      4. void initialize(C var1);
      5. }
       

      查看實現了該這個接口的類進行分析

      以SharedMetadataReaderFactoryContextInitializer實現類為例,跳轉對應jar包,可以看到里面 spring.factories就在key為ApplicationContextInitializer中指定了對應的實現類,例如:

      進入SharedMetadataReaderFactoryContextInitializer,其實現了ApplicationContextInitializer接口,并實現了里面的initialize方法

      現在回到一開始再來看getSpringFactoriesInstance()方法,其核心為loadFactoryNames()方法

      進入loadFactoryNames()方法,可以看到ApplicationContextInitializer的相關獲取內容直接就是從文件“META-INF/spring.factories”中獲取保存的

      (四)加載相關的listeners

      先進入ApplicationListener接口,這個接口只有一個方法onApplicationEvent

       
      1. package org.springframework.context;
      2.  
      3. import java.util.EventListener;
      4.  
      5. @FunctionalInterface
      6. public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
      7. void onApplicationEvent(E var1);
      8. }
       

      查看實現了該這個接口的類進行分析

      以BackgroundPreinitializer實現類為例,跳轉對應jar包,可以看到里面 spring.factories就在key為ApplicationListener中指定了對應的實現類:

       進入BackgroundPreinitializer,其實現了ApplicationListener,并實現了里面的onApplicationEvent

      方法如下:

      現在回到一開始再來看getSpringFactoriesInstance()方法,其處理流程和上面的一樣,即依然是從類路徑下找到META-INF/spring.factories配置的所有ApplicationListener

      (五)決定ApplicationClass主程序

      進入deduceMainApplicationClass方法

      三、SpringApplication啟動過程分析

      SpringBoot啟動方案,包括啟動流程的監聽模塊、加載配置環境模塊、及核心的創建上下文環境模塊以及后續的收尾回調等內容

      (一)監控器監聽容器啟動并進行圖形化頁面處理

      (二)監聽器SpringApplicationRunListeners開啟監聽

      直接開始分析ApringApplicationRunListeners,內含SpringApplicationRunListener的集合,其中starting方法就是對listeners進行遍歷,對每個listener都調用starting方法

      SpringApplicationRunListener和ApplicationListener都是SpringBoot中的事件監聽器,但是它們所監聽的事件和觸發時機有所不同,其區別如下:

      1. 監聽的事件不同
        SpringApplicationRunListener主要監聽SpringApplication運行時的各種事件,例如應用程序開始啟動、應用程序啟動失敗、應用程序啟動完成等事件。而ApplicationListener主要監聽Spring容器中的各種事件,例如Bean加載完成、上下文刷新完成等事件。
      2. 觸發時機不同
        SpringApplicationRunListener在SpringApplication啟動時就開始工作,可以接收到應用程序開始啟動、應用程序啟動失敗、應用程序啟動成功等各種事件。而ApplicationListener則是在Spring容器啟動完成后,才能開始工作,監聽的是Spring容器中的各種事件。
      3. 使用場景不同
        在實際應用中,SpringApplicationRunListener主要用于監聽SpringApplication的啟動過程,例如在應用程序啟動前后執行某些操作、監聽應用程序啟動失敗事件并做出相應的操作等。而ApplicationListener則用于監聽Spring容器中的各種事件,例如在Bean加載完成后做出相應的操作、在上下文刷新完成后更新一些狀態等。

      總之,盡管SpringApplicationRunListener和ApplicationListener都是SpringBoot中的事件監聽器,但是它們所監聽的事件、觸發時機、使用場景等都有所不同,我們需要根據具體的應用需求,選擇合適的監聽器來完成應用程序的事件處理。

      在進入看一下SpringApplicationRunListener這個類

       
      1. package org.springframework.boot;
      2.  
      3. import org.springframework.context.ConfigurableApplicationContext;
      4. import org.springframework.core.env.ConfigurableEnvironment;
      5.  
      6. public interface SpringApplicationRunListener {
      7. void starting();
      8.  
      9. void environmentPrepared(ConfigurableEnvironment environment);
      10.  
      11. void contextPrepared(ConfigurableApplicationContext context);
      12.  
      13. void contextLoaded(ConfigurableApplicationContext context);
      14.  
      15. void started(ConfigurableApplicationContext context);
      16.  
      17. void running(ConfigurableApplicationContext context);
      18.  
      19. void failed(ConfigurableApplicationContext context, Throwable exception);
      20. }
       

      對應方法說明如下

      監聽方法

      運行階段說明

      SpringBoot起始版本

      contextLoaded(ConfigurationApplicationEnvironment)

      ConfigurableApplicationContext完成加載,但仍未啟動;通知監聽器,ApplicationContext已經完成IoC配置

      1.0

      contextPrepared(ConfigurationApplicationEnvironment)

      ConfigurableApplicationContext準備妥當:通知監聽器,ApplicationContext已經創建并初始化完成

      1.0

      environmentPrepared(ConfigurationEnvironment)

      ConfigurationEnvironment準備妥當,允許將其調整

      1.0

      failed(ConfigurationApplicationEnvironment,Throwable)

      Spring應用運行失敗

      2.0

      running(ConfigurationApplicationEnvironment)

      Spring應用正在運行

      2.0

      started(ConfigurationApplicationEnvironment)

      ConfigurableApplicationContext已啟動,此時SpringBean已初始化完成

      2.0

      starting()

      run方法執行的時候立馬執行:通知監聽器,SpringBoot開始執行

      1.0

      總的來說就是創建了應用的監聽器SpringApplicationRunListeners并調用start()開始監聽,先在getRunListeners中獲取了所有的監聽器,然后starting開啟

      (三)environmentPrepared環境準備處理

      分析這段代碼,進入準備環境的方法prepareEnvironment中,可以看到如下:

      首先創建了一個環境ConfigurationEnvironment(有的話就獲取,沒有則創建)

      回到該方法返回的地方,通過this.configureEnvironment對環境進行設置,接著如下:

      環境配置好以后回調了SpringApplicationRunListener的environmentPrepared函數,進入該方法:

      可以看到environmentPrepared環境準備中進行了通知監聽器,Environment準備完成。

      回到開始處,可以看到環境準備完成后通過bindToSpringApplication將環境綁定到程序中。

      (四)banner打印

      打印對應的banner信息

      也就是啟動后的改部分,見如下

      實際中,改圖可以進行替換,只需要在resources增加banner.txt信息即可,例如如下:

      其中的原理可以繼續點開對應后續代碼分析,這個后續中講解替換思路。

      (五)創建Spring應用上下文

      創建應用上下文即IOC過程,IOC容器是驅動整體SpringBoot應用組件的核心,進入該方法:

      這里的創建是根據SpringApplication在構造階段所推斷的web應用類型進行IOC容器的創建,IOC容器就是run返回的內容。

      (六)Spring應用上下文準備階段

      prepareContext方法將listeners、environment、applicationArguments、banner等重要組件與上下文對象關聯,對上下文對象進行進一步配置,進入該方法具體分析:

      可以看到首先分別保存了剛才生成的environment、ApplicationContext,接下來的applyInitializers方法是執行初始化,進入該方法

      方法內部遍歷所有的initializer,然后依次回調里面所有的initialize方法(這些initializer就是在springboot剛啟動時構造new springApplication時添加的),設置完當前環境并完成初始化之后,回調了所有Linsteners的contextPrepared方法

      接下來將命令行參數和banner注冊到IOC容器來,如下:

      最后全部操作都完成后,這個方法回調了Listeners的contextLoaded方法,如上。

      (七)Spring應用上下文刷新階段

      在該方法中首先注冊了一個shutdownHook線程,用來實現SpringBean銷毀生命周期回調

      在執行完refresh之后的控制臺,可以看到tomcat和一些IOC容器的bean都被加載進去了

       

      (八)Spring應用上下文收尾階段

      其中afrerRefresh()并無內容處理,后續的版本中已經沒有改方法了

       
      1. protected void afterRefresh(ConfigurableApplicationContext context,
      2. ApplicationArguments args) {
      3. }
       

      收尾計時器停止,同時調用監聽器的started()。

      (九)回調工作處理

      進入該方法分析

      ApplicationContext就是IOC容器,這個方法從IOC容器中獲取了所有的ApplicationRunner和ConmmandLineRunner,接下來進行遍歷和回調。

      在callRunners使用的這兩個類幾乎可以等價,都是用于做一些客戶自定義的工作,而且是整個流程完成之后才會調用用戶自己定義的實現類的run方法,這兩個run方法的實現方法都是在容器基本初始化好的時候調用的。

      緊接著,如果無異常代碼執行如下:

      監聽器回調running()方法代表SpringApplication正常啟動結束。

      (十)SpringApplication啟動異常處理

      發生異常主要是對異常的處理,我們進入該方法分析

      可以看到這個異常報告類也是支持自定義并且自動配置的,配置結束后,Springboot做了一些基本的收尾工作,返回了應用環境上下文(IOC容器)。

      四、SpringBoot自動配置分析

      Spring Boot 的自動化配置模塊是該框架的核心功能之一,它可以大大簡化應用程序的配置工作。下面是對 Spring Boot 自動化配置模塊的講解和分析:

      1. 自動化配置的原理:Spring Boot 的自動化配置模塊基于約定優于配置的原則。它通過在 classpath 下掃描依賴和配置,自動配置應用程序的各個組件。它使用條件化配置的機制,根據環境和條件自動選擇適當的配置。
      2. 自動配置的實現方式:Spring Boot 自動化配置模塊使用了 @Conditional 注解和條件注解來實現條件化配置。這些注解可以根據一組條件來決定是否啟用某個配置。例如,@ConditionalOnClass 根據 classpath 中是否存在指定的類來判斷是否啟用配置。
      3. 自動配置的加載順序Spring Boot 的自動配置是通過在 classpath 下的 META-INF/spring.factories 文件中定義的自動配置類來實現的。這些自動配置類會被自動加載,并根據條件進行初始化和配置。根據條件的不同,可以有多個自動配置類被加載,它們會按照優先級順序進行配置
      4. 自動配置的自定義:Spring Boot 允許開發者對自動配置進行自定義。你可以使用 @Conditional 注解和條件注解來定義自定義的條件,從而影響自動配置的行為。你還可以使用 @EnableAutoConfiguration 注解來控制自動配置的啟用或禁用。
      5. 自動配置的好處:Spring Boot 的自動化配置模塊帶來了很多好處。它大大減少了手動配置的工作量,提高了開發效率。它提供了合理的默認配置,減少了錯誤配置的風險。同時,它的條件化配置機制使得應用程序更具靈活性,能夠根據不同的環境和需求進行動態的配置。

      總的來說,Spring Boot 的自動化配置模塊是該框架的重要特性之一。它通過約定優于配置的原則和條件化配置機制,實現了自動加載和配置應用程序的各個組件。這為開發者提供了便利和靈活性,并大大簡化了應用程序的配置過程。

      現在回到我們一開始的圖示分析,該配置模塊的主要使用到了SpringFactoriesLoader,即Spring工廠加載器,該對象提供了loadFactoryNames方法,入參為factoryClass和classLoader,即需要傳入工廠類名稱和對應的類加載器,方法會根據指定的classLoader,加載該類加器搜索路徑下的指定文件,即spring.factories文件,傳入的工廠類為接口,獲取到這些實現類的類名后,loadFactoryNames方法返回類名集合,方法調用方得到這些集合后,再通過反射獲取這些類的類對象、構造方法,最終生成實例。

      (一)自動裝配原理分析

      從@SpringBootApplication中的@EnableAutoConfiguration注解中可以看到其import了一個自動配置導入選擇器AutoConfigurationImportSelect

       
      1. package org.springframework.boot.autoconfigure;
      2.  
      3. import java.lang.annotation.Documented;
      4. import java.lang.annotation.ElementType;
      5. import java.lang.annotation.Inherited;
      6. import java.lang.annotation.Retention;
      7. import java.lang.annotation.RetentionPolicy;
      8. import java.lang.annotation.Target;
      9. import org.springframework.context.annotation.Import;
      10.  
      11. @Target({ElementType.TYPE})
      12. @Retention(RetentionPolicy.RUNTIME)
      13. @Documented
      14. @Inherited
      15. @AutoConfigurationPackage
      16. @Import({AutoConfigurationImportSelector.class})
      17. public @interface EnableAutoConfiguration {
      18. String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
      19.  
      20. Class<?>[] exclude() default {};
      21.  
      22. String[] excludeName() default {};
      23. }
       

      其類圖如下

      可以發現其最終實現了ImportSelector(選擇器)和BeanClassLoaderAware(bean類加載器中間件),其中這個選擇器的作用就是導入組件。

      所有自動裝配的邏輯都是在AutoConfigurationImportSelector里面的selectImports方法中實現的

      進入getAutoConfigurationEntry()方法

      進入getCandidateConfigurations()獲取候選配置方法,可以看到核心的SpringFactoriesLoader的loadFactoryNames()方法

      其中SpringFactoriesLoader是Spring Framework工廠機制的加載器,loadFactoryNames是其對應的加載方法,進入這個核心的loadFactoryNames方法中查看

      該處加載原理如下:

      • 掃描所有jar包路徑下 META-INF/spring.factories,這里是通過類加載器生成對應的url路徑
      • 把掃描到的內容包裝成properties對象,并對這個對象的內容進行遍歷,返回map,map的key為接口的全類名,value為接口全部實現類列表(列表里元素去重,防止重復加載),這個value的信息后續會作為loadSpringFactories方法的返回值
      • 在上一步返回的map之中查找并返回指定類名映射的實現類全類名列表

      再看剛才getCandidateConfiguration方法中的getSpringFactoriesLoaderFactoryClass方法,返回的就是EnableAutoConfiguration類

      也就是說要從剛才properties中再獲取這個類對應的值,把它們加到容器中。

      選取mybatis-spring-boot-autoconfigure下的spring.factories文件分析一下:

      每一個 xxxAutoConfiguration類都是容器中的一個組件,都加入到容器中,用它們做自動配置;

      只有進入到容器中,這些自動配置類才會起作用——進行自動配置功能

      (二)條件化自動裝配

      對于使用@Configuration的自動配置類,其條件自動化裝配以@condition為核心。在spring底層中的@conditional注解會根據不同的滿足條件生效整個配置類里面的配置。

      條件化裝配可以分為以下幾類:

      Class條件注解

      注解

      說明

      @ConditionalOnClass

      指定類存在時生效

      @ConditionalOnMissingClass

      指定類缺失時生效

      Bean條件注解

      注解

      說明

      @ConditionalOnBean

      指定Bean存在時生效

      @ConditionalOnMissingBean

      指定Bean缺失時生效

      屬性條件注解

      注解

      說明

      @ConditionalOnProperty

      使用屬性(application.properties)的值判斷是否生效

      Web應用條件注解

      注解

      說明

      @ConditionalOnWebApplication

      是web類型時生效

      @ConditionalOnNotWebApplication

      不是web類型時生效

      其他條件注解

      @Conditional擴展注解

      作用(判斷是否滿足當前指定條件)

      @ConditionalOnJava

      系統的java版本是否符合要求

      @ConditionalOnExpression

      滿足SpEL表達式指定

      @ConditionalOnSingleCandidate

      容器中只有一個指定的Bean,或者這個Bean是首選Bean

      @ConditionalOnResource

      類路徑下是否存在指定資源文件

      @ConditionalOnJndi

      JNDI存在指定項

      分析@ConditionalOnWebApplication

       
      1. package org.springframework.boot.autoconfigure.condition;
      2.  
      3. import java.lang.annotation.Documented;
      4. import java.lang.annotation.ElementType;
      5. import java.lang.annotation.Retention;
      6. import java.lang.annotation.RetentionPolicy;
      7. import java.lang.annotation.Target;
      8. import org.springframework.context.annotation.Conditional;
      9.  
      10. @Target({ElementType.TYPE, ElementType.METHOD})
      11. @Retention(RetentionPolicy.RUNTIME)
      12. @Documented
      13. @Conditional({OnWebApplicationCondition.class})
      14. public @interface ConditionalOnWebApplication {
      15. ConditionalOnWebApplication.Type type() default ConditionalOnWebApplication.Type.ANY;
      16.  
      17. public static enum Type {
      18. ANY,
      19. SERVLET,
      20. REACTIVE;
      21.  
      22. private Type() {
      23. }
      24. }
      25. }
       

      進入OnWebApplicationCondition類,里面有一個getMatchOutcome()方法,就是判斷是否符合當前配置條件

      該方法首先判斷是否使用了這個注釋,然后使用isWebApplication來判斷當前是否是web應用,這些match的方法判斷指定的條件成立,才會給容器添加組件,配置內容才會生效。

      (三)自動配置原理舉例:HttpEncodingAutoConfiguration(HTTP編碼自動配置)

      可以看到以下信息:

      • @Configuration 代表這是一個配置類,類似編寫的配置文件,也可以給容器中添加組件。
      • @EnableConfigurationProperties 啟用指定類的ConfigurationProperties功能,將配置文件application.properties的值和ServerProperties綁定起來,并把ServerProperties加入到IOC容器中。
      • @ConditionalOnClass用來判斷當前項目是否含有這個類,這里CharacterEncodingFilter的作用就是springMVC亂碼解決的過濾器(以前在spring的xml文件中配置的),如果有這個過濾器則配置生效。
      • @ConditionalOnProperty判斷這個配置是否存在,matchIfMissing = true代表即使配置文件中不存在這個屬性也是默認生效的。

      需要注意的是,在spring.factories中的自動配置類不是都能生效的,都有各自的生效條件。根據當前不同條件判斷,來決定這個配置類是否生效;一旦配置類生效,這個配置類就會給容器添加各種組件,這些組件的屬性從對應的properties中獲取,這些類里面的每一個屬性又是和配置文件綁定的。

      五、總結

      Spring Boot 的自動化配置和啟動流程為開發者提供了簡化的開發體驗,降低了配置和啟動的復雜性。通過深入理解 SpringApplication 的啟動步驟、自動配置的原理以及 Spring Boot 如何無縫集成各類組件,我們不僅能更好地運用 Spring Boot,還能更靈活地定制和優化應用。自動配置是 Spring Boot 的核心之一,它通過精巧的條件判斷實現了“按需配置”,確保應用在減少冗余的前提下獲得所需的功能支持。

      在實際開發中,理解這些原理可以幫助我們在遇到問題時更快找到原因,尤其是當我們需要進行調優或者定制配置時,更能從容應對。希望通過本文的分析,你能夠更全面地掌握 Spring Boot 的核心機制,并在實際項目中充分發揮它的優勢。

      posted @ 2025-05-12 17:57  CharyGao  閱讀(118)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产剧情91精品蜜臀一区 | 亚洲 欧美 唯美 国产 伦 综合| 国产精品成人av电影不卡| 熟女一区二区中文字幕| 九九热爱视频精品视频| 日本边添边摸边做边爱| 亚洲国产欧美在线观看片| 日本高清无卡码一区二区久久| 亚洲天码中文字幕第一页| 天堂V亚洲国产V第一次| 另类 亚洲 图片 激情 欧美| 国内揄拍国内精品少妇国语| 国产在线观看黄| 日本中文一区二区三区亚洲| 成人婷婷网色偷偷亚洲男人的天堂| 色综合天天综合天天更新| 草草浮力影院| 亚洲天堂一区二区三区三州| 精品一区二区中文字幕| 久久一日本综合色鬼综合色| 国产三级国产精品国产专区 | 亚洲av永久无码精品水牛影视| 亚洲中文字幕人妻系列| 丰满少妇呻吟高潮经历| 亚洲欧美日韩久久一区二区| 亚洲日韩av无码一区二区三区人 | 一本色道久久88亚洲精品综合| 国产精品视频免费一区二区三区| 国产精品女同性一区二区| 久久天天躁狠狠躁夜夜躁2012| 久久亚洲女同第一区综合| 深夜视频国产在线观看| 国产成年码av片在线观看| 久久精品国产精品亚洲 | 一区二区三区四区黄色片| 欧美乱妇高清无乱码免费| 青青草无码免费一二三区| 国产精品普通话国语对白露脸| 国产精品亚欧美一区二区三区| 四虎在线成人免费观看| 久久av高潮av无码av喷吹|