Spring控制Bean加載順序的操作方法
前言
正常情況下,Spring 容器加載 Bean 的順序是不確定的,那么我們?nèi)绻枰错樞蚣虞d Bean 時(shí)應(yīng)如何操作?本文將詳細(xì)講述我們?nèi)绾尾拍芸刂?Bean 的加載順序。
場景
我創(chuàng)建了 4 個(gè) Class 文件,分別命名為
- FirstInitialization
- SecondInitialization
- ThirdInitialization
- ForthInitialization
我希望這 4 個(gè)類按照 1、2、3、4 的順序加載。
如下圖,直接加載的話,順序是 1、4、2、3,并不能達(dá)到要求。
如何控制
注意:網(wǎng)上很多文章說
Order
注解或Ordered
接口可以控制 Bean 的加載順序,其是并不能,它們的作用是定義 Spring IOC 容器中 Bean 定義類的執(zhí)行順序的優(yōu)先級,并不是定義加載順序。
使用@DependsOn 注解
在需要調(diào)整順序的類上依次加@DependsOn
注解,缺點(diǎn)是類過多的時(shí)候需要一個(gè)個(gè)加注解,且不好維護(hù)。
@Component public class FirstInitialization { @PostConstruct public void init(){ System.out.println("我是第一個(gè)加載!"); } }
@Component @DependsOn("firstInitialization") public class SecondInitialization { @PostConstruct public void init(){ System.out.println("我是第二個(gè)加載!"); } }
@Component @DependsOn("secondInitialization") public class ThirdInitialization { @PostConstruct public void init(){ System.out.println("我是第三個(gè)加載!"); } }
@Component @DependsOn("thirdInitialization") public class ForthInitialization { @PostConstruct public void init(){ System.out.println("我是第四個(gè)加載!"); } }
執(zhí)行結(jié)果如下
基于 ApplicationContextInitializer 接口
接口簡介
這里我簡單介紹一個(gè)這個(gè)接口的用處, 等到整理到相關(guān)源碼的時(shí)候再詳細(xì)介紹。
ApplicationContextInitializer
接口是在 Spring 容器刷新之前執(zhí)行的一個(gè)回調(diào)函數(shù)。
執(zhí)行時(shí)機(jī):
Spring 內(nèi)部執(zhí)行
ConfigurableApplicationContext#refresh()
方法前;SpringBoot 執(zhí)行
run()
方法前。
一般有什么用呢?
在 SpringBoot 應(yīng)用中 Classpath 上會有很多 jar 包,有些 jar 包需要在refresh()
調(diào)用前對應(yīng)用上下文做一些初始化動(dòng)作,因此會提供ApplicationContextInitializer
接口的實(shí)現(xiàn)類,放在如下圖的文件中,這樣會被SpringApplication#initialize
發(fā)現(xiàn),然后完成對應(yīng)初始化。
實(shí)現(xiàn)步驟
首先創(chuàng)建一個(gè)類繼承ApplicationContextInitializer
接口。
public class MyApplicationContextInitializer implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext applicationContext) { //將自定義的BeanFactoryPostProcessor實(shí)現(xiàn)類保存到ApplicationContext中 applicationContext.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor()); } }
創(chuàng)建META-INF/spring.factories
文件。
自定義BeanDefinitionRegistryPostProcessor
。
/** * BeanFactoryPostProcessor的子類 * 允許開發(fā)人員在Bean定義注冊之前和之后對BeanDefinition進(jìn)行自定義處理,例如添加,修改或刪除Bean定義等。 */ public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor { // 初始化需要排序的類,這里要保證插入順序只能用LinkedHashMap private static final Map<String, Class> ORDER_BEAN_MAP = new LinkedHashMap<>() { { put("firstInitialization", FirstInitialization.class); put("secondInitialization", SecondInitialization.class); put("thirdInitialization", ThirdInitialization.class); put("forthInitialization", ForthInitialization.class); } }; @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { Optional.ofNullable(ORDER_BEAN_MAP.keySet()).orElse(new HashSet<>()).stream() .forEach(beanName -> { // 初始化一個(gè) Bean 定義 AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder .genericBeanDefinition().getBeanDefinition(); // 按順序注冊每個(gè)Bean beanDefinition.setBeanClass(ORDER_BEAN_MAP.get(beanName)); registry.registerBeanDefinition(beanName, beanDefinition); }); } }
執(zhí)行結(jié)果如下
以上就是Spring控制Bean加載順序的操作方法的詳細(xì)內(nèi)容,更多關(guān)于Spring控制Bean加載順序的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
shiro并發(fā)人數(shù)登錄控制的實(shí)現(xiàn)代碼
在做項(xiàng)目中遇到這樣的需求要求每個(gè)賬戶同時(shí)只能有一個(gè)人登錄或幾個(gè)人同時(shí)登錄,如果是同時(shí)登錄的多人,要么不讓后者登錄,要么踢出前者登錄,怎么實(shí)現(xiàn)這樣的功能呢?下面小編給大家?guī)砹藄hiro并發(fā)人數(shù)登錄控制的實(shí)現(xiàn)代碼,一起看看吧2017-09-09Spring?populateBean屬性賦值和自動(dòng)注入
這篇文章主要為大家介紹了Spring?populateBean屬性賦值和自動(dòng)注入示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Spring cloud alibaba之Ribbon負(fù)載均衡實(shí)現(xiàn)方案
Spring cloud Ribbon是基于Netflix Ribbon實(shí)現(xiàn)的一套客戶端的負(fù)載均衡工具,Ribbon客戶端提供一系列完善的配置,如超時(shí)、重試等,Ribbon也可以實(shí)現(xiàn)自己的負(fù)載均衡算法,感興趣的朋友跟隨小編一起看看吧2021-07-07SpringCloud微服務(wù)調(diào)用丟失請求頭的問題及解決方案
在Spring Cloud 中微服務(wù)之間的調(diào)用會用到Feign,但是在默認(rèn)情況下,Feign 調(diào)用遠(yuǎn)程服務(wù)存在Header請求頭丟失問題,下面給大家分享SpringCloud微服務(wù)調(diào)用丟失請求頭的問題及解決方案,感興趣的朋友一起看看吧2024-02-02SpringBoot整合Redis的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot整合Redis的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01Java實(shí)現(xiàn)上傳和下載功能(支持多個(gè)文件同時(shí)上傳)
這篇文章主要介紹了Java實(shí)現(xiàn)上傳和下載功能,支持多個(gè)文件同時(shí)上傳,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12Kafka的安裝及接入SpringBoot的詳細(xì)過程
Kafka 是一種高性能、分布式的消息隊(duì)列系統(tǒng),最初由 LinkedIn 公司開發(fā),并于2011年成為 Apache 頂級項(xiàng)目,這篇文章主要介紹了Kafka的安裝及接入SpringBoot,需要的朋友可以參考下2024-05-05Java算法之BFS,DFS,動(dòng)態(tài)規(guī)劃和貪心算法的實(shí)現(xiàn)
廣度優(yōu)先搜索(BFS)和深度優(yōu)先搜索(DFS)是圖遍歷算法中最常見的兩種算法,主要用于解決搜索和遍歷問題。動(dòng)態(tài)規(guī)劃和貪心算法則用來解決優(yōu)化問題。本文就來看看這些算法的具體實(shí)現(xiàn)吧2023-04-04java 下執(zhí)行mysql 批量插入的幾種方法及用時(shí)
java 下執(zhí)行mysql 批量插入的幾種方法及用時(shí),1000次插入方法的比較。2013-04-04