SpringBoot3-核心原理

1. 事件和監聽器

1. 生命周期監聽

場景:監聽應用生命周期

1. 監聽器-SpringApplicationRunListener

  1. 自定義SpringApplicationRunListener監聽事件
    1. 編寫SpringApplicationRunListener 實現類
    2. META-INF/spring.factories 中配置 org.springframework.boot.SpringApplicationRunListener=自己的Listener,還可以指定一個有參構造器,接受兩個參數(SpringApplication application, String[] args)
    3. springboot 在spring-boot.jar中配置了默認的 Listener,如下

/*** Listener先要從 META-INF/spring.factories 讀到** 1、引導: 利用 BootstrapContext 引導整個項目啟動*      starting:              應用開始,SpringApplication的run方法一調用,只要有了 BootstrapContext 就執行*      environmentPrepared:   環境準備好(把啟動參數等綁定到環境變量中),但是ioc還沒有創建;【調一次】* 2、啟動:*      contextPrepared:       ioc容器創建并準備好,但是sources(主配置類)沒加載。并關閉引導上下文;組件都沒創建  【調一次】*      contextLoaded:         ioc容器加載。主配置類加載進去了。但是ioc容器還沒刷新(我們的bean沒創建)。*      =======截止以前,ioc容器里面還沒造bean呢=======*      started:               ioc容器刷新了(所有bean造好了),但是 runner 沒調用。*      ready:                  ioc容器刷新了(所有bean造好了),所有 runner 調用完了。* 3、運行*     以前步驟都正確執行,代表容器running。*/

2. 生命周期全流程

2. 事件觸發時機

1. 各種回調監聽器

  • BootstrapRegistryInitializer 感知特定階段:感知引導初始化
    • META-INF/spring.factories
    • 創建引導上下文bootstrapContext的時候觸發。
    • application.addBootstrapRegistryInitializer();
    • 場景:進行密鑰校對授權。
  • ApplicationContextInitializer: 感知特定階段: 感知ioc容器初始化
    • META-INF/spring.factories
    • application.addInitializers();
  • ApplicationListener: 感知全階段:基于事件機制,感知事件。 一旦到了哪個階段可以做別的事
    • @Bean@EventListener事件驅動
    • SpringApplication.addListeners(…)SpringApplicationBuilder.listeners(…)
    • META-INF/spring.factories
  • SpringApplicationRunListener: 感知全階段生命周期 + 各種階段都能自定義操作; 功能更完善。
    • META-INF/spring.factories
  • ApplicationRunner: 感知特定階段:感知應用就緒Ready。卡死應用,就不會就緒
    • @Bean
  • CommandLineRunner: 感知特定階段:感知應用就緒Ready。卡死應用,就不會就緒
    • @Bean

最佳實戰:

  • 如果項目啟動前做事: BootstrapRegistryInitializerApplicationContextInitializer
  • 如果想要在項目啟動完成后做事:ApplicationRunnerCommandLineRunner
  • 如果要干涉生命周期做事:SpringApplicationRunListener
  • 如果想要用事件機制:ApplicationListener

2. 完整觸發流程

9大事件觸發順序&時機

  1. ApplicationStartingEvent:應用啟動但未做任何事情, 除過注冊listeners and initializers.
  2. ApplicationEnvironmentPreparedEvent: Environment 準備好,但context 未創建.
  3. ApplicationContextInitializedEvent: ApplicationContext 準備好,ApplicationContextInitializers 調用,但是任何bean未加載
  4. ApplicationPreparedEvent: 容器刷新之前,bean定義信息加載
  5. ApplicationStartedEvent: 容器刷新完成, runner未調用

=========以下就開始插入了探針機制============

  1. AvailabilityChangeEventLivenessState.CORRECT應用存活; 存活探針
  2. ApplicationReadyEvent: 任何runner被調用
  3. AvailabilityChangeEventReadinessState.ACCEPTING_TRAFFIC就緒探針,可以接請求
  4. ApplicationFailedEvent :啟動出錯

應用事件發送順序如下:

感知應用是否存活了:可能植物狀態,雖然活著但是不能處理請求。

應用是否就緒了:能響應請求,說明確實活的比較好。

3. SpringBoot 事件驅動開發

應用啟動過程生命周期事件感知(9大事件)應用運行中事件感知(無數種)

  • 事件發布ApplicationEventPublisherAware注入:ApplicationEventMulticaster
  • 事件監聽組件 + @EventListener

事件發布者

@Service
public class EventPublisher implements ApplicationEventPublisherAware {/*** 底層發送事件用的組件,SpringBoot會通過ApplicationEventPublisherAware接口自動注入給我們* 事件是廣播出去的。所有監聽這個事件的監聽器都可以收到*/ApplicationEventPublisher applicationEventPublisher;/*** 所有事件都可以發* @param event*/public void sendEvent(ApplicationEvent event) {//調用底層API發送事件applicationEventPublisher.publishEvent(event);}/*** 會被自動調用,把真正發事件的底層組組件給我們注入進來* @param applicationEventPublisher event publisher to be used by this object*/@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.applicationEventPublisher = applicationEventPublisher;}
}

事件訂閱者

@Service
public class CouponService {@Order(1)@EventListenerpublic void onEvent(LoginSuccessEvent loginSuccessEvent){System.out.println("===== CouponService ====感知到事件"+loginSuccessEvent);UserEntity source = (UserEntity) loginSuccessEvent.getSource();sendCoupon(source.getUsername());}public void sendCoupon(String username){System.out.println(username + " 隨機得到了一張優惠券");}
}

2. 自動配置原理

1. 入門理解

應用關注的三大核心場景配置組件

1. 自動配置流程

  1. 導入starter
  2. 依賴導入autoconfigure
  3. 尋找類路徑下 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
  4. 啟動,加載所有 自動配置類 xxxAutoConfiguration
    1. 給容器中配置功能組件
    2. 組件參數綁定到 屬性類中。xxxProperties
    3. 屬性類配置文件前綴項綁定
    4. @Contional派生的條件注解進行判斷是否組件生效
  1. 效果:
    1. 修改配置文件,修改底層參數
    2. 所有場景自動配置好直接使用
    3. 可以注入SpringBoot配置好的組件隨時使用

2. SPI機制

  • Java中的SPI(Service Provider Interface)是一種軟件設計模式,用于在應用程序中動態地發現和加載組件SPI的思想是,定義一個接口或抽象類,然后通過在classpath中定義實現該接口的類來實現對組件的動態發現和加載。
  • SPI的主要目的是解決在應用程序中使用可插拔組件的問題。例如,一個應用程序可能需要使用不同的日志框架或數據庫連接池,但是這些組件的選擇可能取決于運行時的條件。通過使用SPI,應用程序可以在運行時發現并加載適當的組件,而無需在代碼中硬編碼這些組件的實現類。
  • 在Java中,SPI的實現方式是通過在META-INF/services目錄下創建一個以服務接口全限定名為名字的文件,文件中包含實現該服務接口的類的全限定名。當應用程序啟動時,Java的SPI機制會自動掃描classpath中的這些文件,并根據文件中指定的類名來加載實現類。
  • 通過使用SPI,應用程序可以實現更靈活、可擴展的架構,同時也可以避免硬編碼依賴關系和增加代碼的可維護性。

以上回答來自ChatGPT-3.5

在SpringBoot中,META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

作業:寫一段java的spi機制代碼

3. 功能開關

  • 自動配置:全部都配置好,什么都不用管。 自動批量導入
    • 項目一啟動,spi文件中指定的所有都加載。
  • @EnableXxxx:手動控制哪些功能的開啟; 手動導入。
    • 開啟xxx功能
    • 都是利用 @Import 把此功能要用的組件導入進去

2. 進階理解

1. @SpringBootApplication

@SpringBootConfiguration

就是: @Configuration ,容器中的組件,配置類。spring ioc啟動就會加載創建這個類對象

@EnableAutoConfiguration:開啟自動配置

開啟自動配置

@AutoConfigurationPackage:掃描主程序包:加載自己的組件
  • 利用 @Import(AutoConfigurationPackages.Registrar.class) 想要給容器中導入組件。
  • 把主程序所在的的所有組件導入進來。
  • 為什么SpringBoot默認只掃描主程序所在的包及其子包

@Import(AutoConfigurationImportSelector.class):加載所有自動配置類:加載starter導入的組件
		List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).getCandidates();

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

@ComponentScan

組件掃描:排除一些組件(哪些不要)

排除前面已經掃描進來的配置類、和自動配置類

@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

2. 完整啟動加載流程

生命周期啟動加載流程

3. 自定義starter

場景:抽取聊天機器人場景,它可以打招呼

效果:任何項目導入此starter都具有打招呼功能,并且問候語中的人名需要可以在配置文件中修改

  • 1. 創建自定義starter項目,引入spring-boot-starter基礎依賴
  • 2. 編寫模塊功能,引入模塊所有需要的依賴。
  • 3. 編寫xxxAutoConfiguration自動配置類,幫其他項目導入這個模塊需要的所有組件
  • 4. 編寫配置文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports指定啟動需要加載的自動配置
  • 5. 其他項目引入即可使用

1. 業務代碼

自定義配置有提示。導入以下依賴重啟項目,再寫配置文件就有提示

@ConfigurationProperties(prefix = "robot")  //此屬性類和配置文件指定前綴綁定
@Component
@Data
public class RobotProperties {private String name;private String age;private String email;
}

<!--        導入配置處理器,配置文件自定義的properties配置都會有提示--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>

2. 基本抽取

  • 創建starter項目,把公共代碼需要的所有依賴導入
  • 把公共代碼復制進來
  • 自己寫一個 RobotAutoConfiguration,給容器中導入這個場景需要的所有組件
  • 為什么這些組件默認不會掃描進去?
  • starter所在的包和 引入它的項目的主程序所在的包不是父子層級
  • 別人引用這個starter,直接導入這個 RobotAutoConfiguration,就能把這個場景的組件導入進來
  • 功能生效。
  • 測試編寫配置文件

3. 使用@EnableXxx機制

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import(RobotAutoConfiguration.class)
public @interface EnableRobot {}

別人引入starter需要使用 @EnableRobot開啟功能

4. 完全自動配置

  • 依賴SpringBoot的SPI機制
  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中編寫好我們自動配置類的全類名即可
  • 項目啟動,自動加載我們的自動配置類

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717138.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717138.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717138.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【藍橋杯】錯誤票據

今天是2024年3月1號&#xff0c;藍橋杯比賽還有一個月的時間&#xff0c;雖說自己不指望拿獎吧&#xff0c;但是還是有些莫i名的焦慮&#xff0c;這道題目都做不出來&#xff0c;感覺自己真的有點菜啊&#xff01;但是還好啦&#xff0c;我覺得是因為我沒有題感&#xff0c;慢慢…

spring boot 整合 minio存儲 【使用篇】

導入依賴 <!--minio--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.0.3</version></dependency> yml配置&#xff08;默認配置&#xff09; max-file-size: 200MB 設置文件最大…

華為od機試C卷-開源項目熱度榜單

1、題目描述 某個開源社區希望將最近熱度比較高的開源項目出一個榜單&#xff0c;推薦給社區里面的開發者。 對于每個開源項目&#xff0c;開發者可以進行關注(watch)、收藏(star)、fork、提issue、提交合并請求(MR)等。 數據庫里面統計了每個開源項目關注、收藏、fork、issue…

微服務API網關---APISIX

最近在做微服務調研&#xff0c;看到了apisix這個網關&#xff0c;于是進行了初步了解一下。 微服務是指&#xff0c;將大型應用分解成多個獨立的組件&#xff0c;其中每個組件都各自的負責對應項目。 系統的架構大致經歷了&#xff1a;單體應用架構–> SOA架構 -->微服務…

Linux多線程服務端編程:使用muduo C++網絡庫 學習筆記 附錄D 關于TCP并發連接的幾個思考題與試驗

前幾天作者在新浪微博上出了兩道有關TCP的思考題&#xff0c;引發了一場討論&#xff08;http://weibo.com/1701018393/eCuxDrtaONn&#xff09;。 第一道初級題目是&#xff1a;有一臺機器&#xff0c;它有一個IP&#xff0c;上面運行了一個TCP服務程序&#xff0c;程序只偵聽…

StarRocks實戰——松果出行實時數倉實踐

目錄 一、背景 二、松果出行實時OLAP的演進 2.1 實時數倉1.0的架構 2.2 實時數倉2.0的架構 2.3 實時數倉3.0的架構 三、StarRocks 的引入 四、StarRocks在松果出行的應用 4.1 在訂單業務中的應用 4.2 在車輛方向的應用 4.3 StarRocks “極速統一” 落地 4.4 StarRoc…

Lambda、Function、StreamAPI詳解

目錄 1、Lambda 2、Function 3、StreamAPI 中間操作&#xff1a;Intermediate Operations 終止操作&#xff1a;Terminal Operation 1、Lambda Java8語法糖&#xff1a;參數列表 箭頭 方法體 package com.atguiggu.lambda;import java.util.*; import java.util.funct…

分布式ID生成系統之雪花算法詳解

在當今的云計算和微服務架構盛行的時代&#xff0c;分布式系統已成為軟件開發的重要組成部分。隨著系統規模的擴大和業務的復雜化&#xff0c;對數據一致性和唯一性的要求也越來越高&#xff0c;尤其是在全局唯一標識符&#xff08;ID&#xff09;的生成上。因此&#xff0c;分…

代碼隨想錄算法訓練營Day48 | 121.買賣股票的最佳時機、122.買賣股票的最佳時機 II

121.買賣股票的最佳時機 &#xff08;想寫動態規劃寫著寫著變成貪心了&#xff09; 半貪心半動規&#xff1a; int maxProfit(vector<int>& prices) {vector<int> dp(prices.size(), 0);int minVal prices[0];for (int i 1; i < prices.size(); i) {//…

yolov5訓練太慢的解決方案

問題原因 訓練太慢大多是因為沒有安裝CUDA和pytorch&#xff0c;導致的只有cpu在跑&#xff0c;顯卡沒跑 這就是很典型的。 解決方案 第一步&#xff1a;安裝CUDA 在本機上面安裝CUDA,記住只有N卡可以安裝&#xff0c;一開始的電腦是自帶CUDA的。 如果不是自帶的CUDA&…

Apache Paimon Flink引擎解析

Paimon 支持 Flink 1.17, 1.16, 1.15 和 1.14&#xff0c;當前 Paimon 提供了兩類 Jar 包&#xff0c;一類支持數據讀寫&#xff0c;另一類支持其它操作&#xff08;compaction&#xff09; Version Type Jar Flink 1.18 Bundled Jar paimon-flink-1.18-0.7…

SentenceTransformer簡單使用

SentenceTransformer簡單使用 1 SentenceTransformer介紹 SentenceTransformer主要用于對句子、文本和圖像進行嵌入。可用于文本和圖像的相似度對比查找等 # SentenceTransformer官網地址 https://www.sbert.net/# 安裝SentenceTransformer pip install -U sentence-transfo…

求數字的每一位之和

求數字的每一位之和 題目描述&#xff1a;解法思路&#xff1a;解法代碼&#xff1a;運行結果&#xff1a; 題目描述&#xff1a; 輸入一個整數m&#xff0c;求這個整數m的每?位之和&#xff0c;并打印。 測試1&#xff1a; 輸?&#xff1a;1234 輸出&#xff1a;10 測試2&…

土壤侵蝕量化評估

根據之前的文章,已經算出了R、K、LS、C、P 現在計算土壤侵蝕,將幾個前期制作好的因子的TIFF文件,用柵格計算器相乘 發現局部地區存在輕度侵蝕,大部分區域是微度侵蝕 然后對比了一下范圍 其中的幾個因子都在文獻范圍內,說明計算結果并未出錯,可能就是研究區正常范圍和結…

6020一拖二快充線:手機充電的革命性創新

在快節奏的現代生活中&#xff0c;手機已不僅僅是一個通訊工具&#xff0c;更是我們工作、學習和娛樂的得力助手。然而&#xff0c;手機的電量問題一直是困擾著我們的難題。為了解決這個問題&#xff0c;市場上出現了一種名為“一拖二快充線”的充電設備&#xff0c;它不僅具備…

etcd入門-(1)安裝篇

一、etcd安裝 https://github.com/etcd-io/etcd/releases 根據需要下載安裝etcd, 確保添加到環境變量 執行 etcd -v 查看安裝版本 二、etcd運行 本地運行集群 1.首先安裝goreman go install github.com/mattn/goremanlatest2.準備Procfile 將腳本下載到本地&#xff0c;或者復…

八. 實戰:CUDA-BEVFusion部署分析-分析BEVFusion中各個ONNX

目錄 前言0. 簡述1. camera.backbone.onnx(fp16)2. camera.backbone.onnx(int8)3. camera.vtransform.onnx(fp16)4. fuser.onnx(fp16)5. fuser.onnx(int8)6. lidar.backbone.xyz.onnx7. head.bbox.onnx(fp16)總結下載鏈接參考 前言 自動駕駛之心推出的《CUDA與TensorRT部署實戰…

每日一類:Qt中的萬能容器

在Qt框架中&#xff0c;QVariant類扮演著一個非常重要的角色。它是一個萬能容器類&#xff0c;可以存儲Qt中的任何基本類型數據&#xff0c;包括自定義類型。這種靈活性使得QVariant成為Qt編程中不可或缺的工具&#xff0c;特別是在需要處理不同類型數據或進行對象間通信時。 …

Unity UGUI之Scrollbar基本了解

Unity的Scrollbar組件是用于在UI中創建滾動條的組件之一。滾動條通常與其他可滾動的UI元素&#xff08;如滾動視圖或列表&#xff09;一起使用&#xff0c;以便用戶可以在內容超出可見區域時滾動內容。 以下是Scrollbar的基本信息和用法: 1、創建 在Unity的Hierarchy視圖中右…

柯西矩陣介紹

經典定義 柯西矩陣&#xff08;Cauchy Matrix&#xff09;&#xff0c;是一種特殊類型的矩陣&#xff0c;它在數學中的多個領域&#xff0c;包括線性代數、數值分析和插值理論中都有重要應用。柯西矩陣以19世紀法國數學家奧古斯丁-路易柯西的名字命名。 柯西矩陣是一個方陣&am…