Spring控制bean加載順序使用詳解
1.誤區(qū)
1.1 使用@Order注解去設(shè)置Ben的加載順序(Order里面的數(shù)值越小優(yōu)先級越高)
分別創(chuàng)建Config1,Config2
@Component
@Order(1)
public class Config1 {
public Config1(){
System.out.println("Config1構(gòu)建了.........");
}
}
?
@Component
@Order(2)
public class Config2 {
public Config2(){
System.out.println("Config2構(gòu)建了.........");
}
}
?期間我還嘗試著將@Component都改為使用@Configuration,結(jié)果仍然不變
總結(jié):嘗試過同包下,不同包下。最終測試結(jié)果為:一般情況下會按照SPring類的書寫的順序去創(chuàng)建,但是也不一定,最終其實得看你的編譯出來的文件,的Class文件到底是什么樣子的,包括操作系統(tǒng)文件的排序規(guī)則等一系列的因素。反正這個順序是不確定的。如果包的順序Config1在Config2的下面,就算Config1的@Order值小于Config2的值也沒有用。
1.2使用@AutoConfigureAfter控制Ben的加載順序(當(dāng)前配置類在指定配置類之后執(zhí)行)
@AutoConfigureBefore(當(dāng)前配置類在指定配置類之前執(zhí)行)
@AutoConfigureOrder(指定優(yōu)先級,數(shù)值越小,優(yōu)先級越高)
@Configuration
@AutoConfigureAfter(Config1.class)
public class Config2 {
public Config2(){
System.out.println("Config2構(gòu)建了.........");
}
}
@Configuration
public class Config1 {
public Config1(){
System.out.println("Config1構(gòu)建了.........");
}
}@Configuration
@AutoConfigureAfter(Config1.class)
public class Config2 {
public Config2(){
System.out.println("Config2構(gòu)建了.........");
}
}
@Configuration
public class Config1 {
public Config1(){
System.out.println("Config1構(gòu)建了.........");
}
}@Configuration
@AutoConfigureOrder(1)
public class Config2 {
public Config2(){
System.out.println("Config2構(gòu)建了.........");
}
}
@Configuration
@AutoConfigureOrder(2)
public class Config1 {
public Config1(){
System.out.println("Config1構(gòu)建了.........");
}
}以上三個注解在同包和不同包都是不起作用的,和@Order是一樣的也是通過書寫順序去創(chuàng)建的。
此時這里使用@Component是不起作用的,但是上面的@Order注解就不會有影響,無聊是使用@Configurantion還是@Component都是一個效果。
解決:在resources下新建META-INF/spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.juzi.test.config.Config2,\ com.juzi.test.config.Config1
結(jié)果我就不粘出來了,感興趣的小伙伴可以去嘗試一下。
2.正確的控制方法
2.1使用@DependsOn("Bean B")注解控制(告訴Spring容器Bean B 應(yīng)該被提前初始化)
創(chuàng)建AircraftTask、CarTask、TrainTask

目前創(chuàng)建的順序是 Aircraft -> CarTask -> Train
理想的創(chuàng)建順序 Train -> Aircraft -> TrainCar
@Configuration
@DependsOn("trainTask")
public class AircraftTask {
@PostConstruct
public void init(){
System.out.println("Aircraft獲取Train存入redis的數(shù)據(jù)..........");
}
}
@Configuration
@DependsOn("aircraftTask")
public class CarTask {
@PostConstruct
public void init(){
System.out.println("CarTask獲取到Aircraft的數(shù)據(jù)..........");
}
}
@Configuration
public class TrainTask {
@PostConstruct
public void init(){
System.out.println("Train初查詢數(shù)據(jù)存入redis..........");
}
}結(jié)果:和理想的結(jié)果一致

但是如果像以上這種依賴的類數(shù)量過多的話這樣寫注解容易寫錯,我們可以使用以下方法 :
2.2使用BeanDefinitionRegistryPostProcessor和ApplicationContextInitializer去控制
對這兩個類不是很熟悉的同學(xué)可以去下載Spring源碼簡單的閱讀一下。
public class CarTask {
@PostConstruct
public void init(){
System.out.println("CarTask獲取到Aircraft的數(shù)據(jù)..........");
}
}
public class AircraftTask {
@PostConstruct
public void init(){
System.out.println("Aircraft獲取Train存入redis的數(shù)據(jù)..........");
}
}
public class TrainTask {
@PostConstruct
public void init(){
System.out.println("Train初查詢數(shù)據(jù)存入redis..........");
}
}這里不需要使用@Configuration或@Component注解,下面會對它們進(jìn)行手動的添加到容器中。
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
AbstractBeanDefinition beanDefinition2 = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition2.setBeanClass(TrainTask.class);
registry.registerBeanDefinition("trainTask",beanDefinition2);
AbstractBeanDefinition beanDefinition1 = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition1.setBeanClass(AircraftTask.class);
registry.registerBeanDefinition("aircraftTask",beanDefinition1);
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(CarTask.class);
registry.registerBeanDefinition("carTaskTask",beanDefinition);
//相當(dāng)于往Spring容器初始化的時的那個List里面添加了一個Bean 只要在掃描之前執(zhí)行了postProcessBeanDefinitionRegistry 方法 那么就會安裝List里面存放的順序
//生成Bean
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}public class MyApplicationContextInitiaLizer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
configurableApplicationContext.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
}
}resources下新建META-INF/spring.factories文件 配置MyApplicationContextInitiaLizer的全限定類名即可。
#org.springframework.context.ApplicationContextInitializer=com.example.demo11.config.MyApplicationContextInitiaLizer
結(jié)果:也和預(yù)期的一致

以上就是Spring控制bean加載順序使用詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring控制bean加載順序的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springcloud client指定注冊到eureka的ip與端口號方式
這篇文章主要介紹了springcloud client指定注冊到eureka的ip與端口號方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
在 Spring Boot 中使用異步線程時的 HttpServletReque
文章討論了在SpringBoot中使用異步線程時,由于HttpServletRequest復(fù)用導(dǎo)致的Cookie解析失敗問題,為了解決這個問題,文章推薦了使用HttpServletRequestWrapper創(chuàng)建請求副本、手動傳遞請求上下文和延遲請求清理等方法,感興趣的朋友一起看看吧2025-03-03
HashMap工作原理_動力節(jié)點Java學(xué)院整理
這篇文章主要介紹了HashMap工作原理_動力節(jié)點Java學(xué)院整理,需要的朋友可以參考下2017-04-04
Java實現(xiàn)一鍵生成表controller,service,mapper文件
這篇文章主要為大家詳細(xì)介紹了如何利用Java語言實現(xiàn)一鍵生成表controller,service,mapper文件,文中的示例代碼講解詳細(xì),需要的可以收藏一下2023-05-05
Spring之關(guān)于PropertyDescriptor的擴展剖析
這篇文章主要介紹了Spring之關(guān)于PropertyDescriptor的擴展剖析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
Spring?AOP注解配置與XML配置雙實戰(zhàn)教程
本文詳細(xì)介紹了面向切面編程(AOP)的概念、快速入門、核心概念、切點確定、通知分類、獲取被增強方法相關(guān)信息、應(yīng)用案例、XML配置、多切面順序問題以及AOP原理中的動態(tài)代理,通過實例展示了如何在Spring框架中使用AOP進(jìn)行方法增強,感興趣的朋跟隨小編一起看看吧2025-11-11
SpringBoot項目啟動時如何將需要數(shù)據(jù)添加到redis緩存
文章介紹了使用Java注解@PostConstruct進(jìn)行項目啟動時加載,并使用Spring和Redis進(jìn)行數(shù)據(jù)緩存的操作,通過`setCacheObject`方法將數(shù)據(jù)存儲到Redis中,并提供了清空緩存的方法2026-04-04

