成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何正確控制springboot中bean的加載順序總結

開發 后端
你明明已經把相關的Bean都注冊進spring上下文了呀。這時候你需要通過一些手段來控制springboot中的bean加載順序。

 1.為什么需要控制加載順序

springboot遵從約定大于配置的原則,極大程度的解決了配置繁瑣的問題。在此基礎上,又提供了spi機制,用spring.factories可以完成一個小組件的自動裝配功能。

在一般業務場景,可能你不大關心一個bean是如何被注冊進spring容器的。只需要把需要注冊進容器的bean聲明為@Component即可,spring會自動掃描到這個Bean完成初始化并加載到spring上下文容器。

而當你在項目啟動時需要提前做一個業務的初始化工作時,或者你正在開發某個中間件需要完成自動裝配時。你會聲明自己的Configuration類,但是可能你面對的是好幾個有互相依賴的Bean。如果不加以控制,這時候可能會報找不到依賴的錯誤。

但是你明明已經把相關的Bean都注冊進spring上下文了呀。這時候你需要通過一些手段來控制springboot中的bean加載順序。

2.幾個誤區

在正式說如何控制加載順序之前,先說2個誤區。

在標注了@Configuration的類中,寫在前面的@Bean一定會被先注冊

這個不存在的,spring在以前xml的時代,也不存在寫在前面一定會被先加載的邏輯。因為xml不是漸進的加載,而是全部parse好,再進行依賴分析和注冊。到了springboot中,只是省去了xml被parse成spring內部對象的這一過程,但是加載方式并沒有大的改變。

利用@Order這個標注能進行加載順序的控制

嚴格的說,不是所有的Bean都可以通過@Order這個標注進行順序的控制。你把@Order這個標注加在普通的方法上或者類上一點鳥用都沒有。

那@Order能控制哪些bean的加載順序呢,我們先看看官方的解釋: 

  1. {@code @Order} defines the sort order for an annotated component. Since Spring 4.0, annotation-based ordering is supported for many kinds of components in Spring, even for collection injection where the order values of the target components are taken into account (either from their target class or from their {@code @Bean} method). While such order values may influence priorities at injection points, please be aware that they do not influence singleton startup order which is an orthogonal concern determined by dependency relationships and {@code @DependsOn} declarations (influencing a runtime-determined dependency graph). 

最開始@Order注解用于切面的優先級指定;在 4.0 之后對它的功能進行了增強,支持集合的注入時,指定集合中 bean 的順序,并且特別指出了,它對于但實例的 bean 之間的順序,沒有任何影響。

目前用的比較多的有以下3點:

  • 控制AOP的類的加載順序,也就是被@Aspect標注的類
  • 控制ApplicationListener實現類的加載順序
  • 控制CommandLineRunner實現類的加載順序

3.如何控制

3.1@DependsOn

@DependsOn注解可以用來控制bean的創建順序,該注解用于聲明當前bean依賴于另外一個bean。所依賴的bean會被容器確保在當前bean實例化之前被實例化。

示例: 

  1. @Configuration  
  2. public class BeanOrderConfiguration {  
  3.     @Bean  
  4.     @DependsOn("beanB")  
  5.     public BeanA beanA(){  
  6.         System.out.println("bean A init");  
  7.         return new BeanA();  
  8.     }  
  9.     @Bean  
  10.     public BeanB beanB(){  
  11.         System.out.println("bean B init");  
  12.         return new BeanB();  
  13.     }  
  14.     @Bean  
  15.     @DependsOn({"beanD","beanE"})  
  16.     public BeanC beanC(){  
  17.         System.out.println("bean C init"); 
  18.          return new BeanC();  
  19.     }  
  20.     @Bean  
  21.     @DependsOn("beanE")  
  22.     public BeanD beanD(){  
  23.         System.out.println("bean D init");  
  24.         return new BeanD();  
  25.     }  
  26.     @Bean  
  27.     public BeanE beanE(){  
  28.         System.out.println("bean E init");  
  29.         return new BeanE();  
  30.     }  

以上代碼bean的加載順序為: 

  1. bean B init  
  2. bean A init  
  3. bean E init  
  4. bean D init  
  5. bean C init 

@DependsOn的使用:

  • 直接或者間接標注在帶有@Component注解的類上面;
  • 直接或者間接標注在帶有@Bean注解的方法上面;
  • 使用@DependsOn注解到類層面僅僅在使用 component-scanning 方式時才有效,如果帶有@DependsOn注解的類通過XML方式使用,該注解會被忽略,<bean depends-on="..."/>這種方式會生效。

3.2 參數注入

在@Bean標注的方法上,如果你傳入了參數,springboot會自動會為這個參數在spring上下文里尋找這個類型的引用。并先初始化這個類的實例。

利用此特性,我們也可以控制bean的加載順序。

示例: 

  1. @Bean  
  2. public BeanA beanA(BeanB demoB){  
  3.   System.out.println("bean A init");  
  4.   return new BeanA();  
  5.  
  6. @Bean  
  7. public BeanB beanB(){  
  8.   System.out.println("bean B init");  
  9.   return new BeanB();  
  10.  

以上結果,beanB先于beanA被初始化加載。

需要注意的是,springboot會按類型去尋找。如果這個類型有多個實例被注冊到spring上下文,那你就需要加上@Qualifier("Bean的名稱")來指定

3.3 利用bean的生命周期中的擴展點

在spring體系中,從容器到Bean實例化&初始化都是有生命周期的,并且提供了很多的擴展點,允許你在這些步驟時進行邏輯的擴展。

這些可擴展點的加載順序由spring自己控制,大多數是無法進行干預的。我們可以利用這一點,擴展spring的擴展點。在相應的擴展點加入自己的業務初始化代碼。從來達到順序的控制。

具體關于spring容器中大部分的可擴展點的分析,之前已經寫了一篇文章詳細介紹了:《Springboot啟動擴展點超詳細總結,再也不怕面試官問了》。

3.4 @AutoConfigureOrder

這個注解用來指定配置文件的加載順序。但是在實際測試中發現,以下這樣使用是不生效的: 

  1. @Configuration  
  2. @AutoConfigureOrder(2)  
  3. public class BeanOrderConfiguration1 {  
  4.     @Bean  
  5.     public BeanA beanA(){  
  6.         System.out.println("bean A init");  
  7.         return new BeanA();  
  8.     }  
  9. @Configuration  
  10. @AutoConfigureOrder(1)  
  11. public class BeanOrderConfiguration2 {  
  12.     @Bean  
  13.     public BeanB beanB(){  
  14.         System.out.println("bean B init");  
  15.         return new BeanB();  
  16.     }  
  17.  

無論你2個數字填多少,都不會改變其加載順序結果。

那這個@AutoConfigureOrder到底是如何使用的呢。

經過測試發現,@AutoConfigureOrder只能改變外部依賴的@Configuration的順序。如何理解是外部依賴呢。

能被你工程內部scan到的包,都是內部的Configuration,而spring引入外部的Configuration,都是通過spring特有的spi文件:spring.factories

換句話說,@AutoConfigureOrder能改變spring.factories中的@Configuration的順序。

具體使用方式: 

  1. @Configuration  
  2. @AutoConfigureOrder(10)  
  3. public class BeanOrderConfiguration1 {  
  4.     @Bean  
  5.     public BeanA beanA(){  
  6.         System.out.println("bean A init");  
  7.         return new BeanA();  
  8.     }  
  9.  
  10. @Configuration  
  11. @AutoConfigureOrder(1)  
  12. public class BeanOrderConfiguration2 {  
  13.     @Bean  
  14.     public BeanB beanB(){  
  15.         System.out.println("bean B init");  
  16.         return new BeanB();  
  17.     }  
  18.  

spring.factories: 

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\  
  2.   com.example.demo.BeanOrderConfiguration1,\  
  3.   com.example.demo.BeanOrderConfiguration2  

4.總結

其實在工作中,我相信很多人碰到過復雜的依賴關系的bean加載,把這種不確定性交給spring去做,還不如我們自己去控制,這樣在閱讀代碼的時候 ,也能輕易看出bean之間的依賴先后順序。 

 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2024-05-29 08:19:03

2018-07-06 14:21:56

云計算云安全云端

2023-10-18 18:38:44

數據校驗業務

2023-12-04 09:23:49

分布式消息

2022-09-16 11:41:17

Spring代碼

2020-10-15 12:52:46

SpringbootJava編程語言

2023-10-25 10:21:24

瀏覽器HTTP請求

2023-03-08 09:59:39

SpringBean注入

2023-09-28 08:15:05

SpringBean加載

2021-07-28 07:22:40

SQL順序Hive

2010-01-05 14:01:27

JSON.NET

2024-01-23 08:47:13

BeanSpring加載方式

2023-01-30 07:41:43

2020-11-04 07:05:57

技術總監同事

2024-02-05 18:23:23

父進程應用程序程序

2020-09-11 19:20:18

云計算企業管理

2012-02-14 13:39:57

Java

2021-07-27 07:49:39

SpringBoot配置環境

2010-06-13 15:10:49

MySQL loadd

2024-01-22 09:01:00

SpringBoot接口代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91久久夜色精品国产网站 | 欧美专区日韩专区 | 国产一级片在线播放 | 日韩成年人视频在线 | 国产精品中文字幕在线观看 | 91精品国产91久久久久久吃药 | 超碰在线人人 | 亚洲乱码一区二区三区在线观看 | 国内自拍偷拍 | 亚洲精品在线免费观看视频 | 日韩精品极品视频在线观看免费 | 337p日本欧洲亚洲大胆精蜜臀 | 日韩一区二区免费视频 | 九九热精品在线视频 | 中国91av | 国产精品毛片一区二区在线看 | 亚洲欧美一区二区三区国产精品 | 日韩资源 | www.亚洲.com| 久久久一区二区三区 | 在线免费观看黄a | 日日噜噜噜夜夜爽爽狠狠视频, | 一区二区三区四区av | 国产精品久久久久久久久免费软件 | 日韩字幕一区 | www.久久久久久久久久久 | 国产精品综合色区在线观看 | 成人网在线观看 | 国产高清性xxxxxxxx | 久久亚洲一区 | 天堂色| 91香蕉视频在线观看 | 日韩精品一二三 | 国产精品久久久久一区二区 | 国产韩国精品一区二区三区 | 免费一级黄色 | 日韩欧美一区二区三区 | 久久99精品久久久久久青青日本 | 一久久久| 亚洲国产小视频 | 岛国视频|