Spring控制bean加載順序使用詳解
1.誤區(qū)
1.1 使用@Order注解去設(shè)置Ben的加載順序(Order里面的數(shù)值越小優(yōu)先級(jí)越高)
分別創(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é):嘗試過(guò)同包下,不同包下。最終測(cè)試結(jié)果為:一般情況下會(huì)按照SPring類的書(shū)寫(xiě)的順序去創(chuàng)建,但是也不一定,最終其實(shí)得看你的編譯出來(lái)的文件,的Class文件到底是什么樣子的,包括操作系統(tǒng)文件的排序規(guī)則等一系列的因素。反正這個(gè)順序是不確定的。如果包的順序Config1在Config2的下面,就算Config1的@Order值小于Config2的值也沒(méi)有用。
1.2使用@AutoConfigureAfter控制Ben的加載順序(當(dāng)前配置類在指定配置類之后執(zhí)行)
@AutoConfigureBefore(當(dāng)前配置類在指定配置類之前執(zhí)行)
@AutoConfigureOrder(指定優(yōu)先級(jí),數(shù)值越小,優(yōu)先級(jí)越高)
@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)建了........."); } }
以上三個(gè)注解在同包和不同包都是不起作用的,和@Order是一樣的也是通過(guò)書(shū)寫(xiě)順序去創(chuàng)建的。
此時(shí)這里使用@Component是不起作用的,但是上面的@Order注解就不會(huì)有影響,無(wú)聊是使用@Configurantion還是@Component都是一個(gè)效果。
解決:在resources下新建META-INF/spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.juzi.test.config.Config2,\ com.juzi.test.config.Config1
結(jié)果我就不粘出來(lái)了,感興趣的小伙伴可以去嘗試一下。
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ù)量過(guò)多的話這樣寫(xiě)注解容易寫(xiě)錯(cuò),我們可以使用以下方法 :
2.2使用BeanDefinitionRegistryPostProcessor和ApplicationContextInitializer去控制
對(duì)這兩個(gè)類不是很熟悉的同學(xué)可以去下載Spring源碼簡(jiǎn)單的閱讀一下。
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注解,下面會(huì)對(duì)它們進(jìn)行手動(dòng)的添加到容器中。
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容器初始化的時(shí)的那個(gè)List里面添加了一個(gè)Bean 只要在掃描之前執(zhí)行了postProcessBeanDefinitionRegistry 方法 那么就會(huì)安裝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加載順序的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java實(shí)現(xiàn)gif動(dòng)畫(huà)效果(java顯示動(dòng)態(tài)圖片)
這篇文章主要介紹了java實(shí)現(xiàn)gif動(dòng)畫(huà)效果示例(java顯示動(dòng)態(tài)圖片),需要的朋友可以參考下2014-04-04java實(shí)現(xiàn)ATM取款項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)ATM取款項(xiàng)目的實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06Springboot結(jié)合JDBC實(shí)現(xiàn)雙數(shù)據(jù)源實(shí)例
這篇文章主要為大家介紹了Springboot結(jié)合JDBC實(shí)現(xiàn)雙數(shù)據(jù)源實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12Spring中的BeanDefinition注冊(cè)流程詳解
這篇文章主要介紹了Spring中的BeanDefinition注冊(cè)流程詳解, NamespaceHandler簡(jiǎn)單來(lái)說(shuō)就是命名空間處理器,Spring為了開(kāi)放性提供了NamespaceHandler機(jī)制,這樣我們就可以根據(jù)需求自己來(lái)處理我們?cè)O(shè)置的標(biāo)簽元素,需要的朋友可以參考下2023-12-12java中double類型運(yùn)算結(jié)果異常的解決方法
下面小編就為大家?guī)?lái)一篇java中double類型運(yùn)算結(jié)果異常的解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12