springboot中bean的加載順序問(wèn)題
一、為什么要控制
當(dāng)你在項(xiàng)目啟動(dòng)時(shí)需要提前做一個(gè)業(yè)務(wù)的初始化工作時(shí),或者你正在開(kāi)發(fā)某個(gè)中間件需要完成自動(dòng)裝配時(shí)。
你會(huì)聲明自己的Configuration類,但是可能你面對(duì)的是好幾個(gè)有互相依賴的Bean。
如果不加以控制,這時(shí)候可能會(huì)報(bào)找不到依賴的錯(cuò)誤,這個(gè)時(shí)候需要通過(guò)一些手段來(lái)控制springboot中的bean加載順序。
二、怎么控制
@DependsOn
@DependsOn注解可以用來(lái)控制bean的創(chuàng)建順序,該注解用于聲明當(dāng)前bean依賴于另外一個(gè)bean。
所依賴的bean會(huì)被容器確保在當(dāng)前bean實(shí)例化之前被實(shí)例化。
與@Component或@Bean配合使用
demo
@Slf4j @Configuration @ConfigurationProperties(prefix = "dict") public class SpringConfig { @Component(value = "EventSource") public class EventSource { public EventSource(){ System.out.println("事件源創(chuàng)建"); } } /** * 監(jiān)聽(tīng)類 */ @Component @DependsOn(value = {"EventSource"}) public class EventTListener { public EventTListener(){ System.out.println("監(jiān)聽(tīng)器創(chuàng)建"); } } }
參數(shù)注入
package com.sinosoft.springbootplus.test.config; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; /** * @author lsh * @date 2022/2/25 */ @Slf4j @Configuration @ConfigurationProperties(prefix = "dict") public class SpringConfig { @Component public class Event{ public Event(){ System.out.println("事件事件"); } } @Component public class EventSource{ public EventSource(Event e){ System.out.println("事件源創(chuàng)建"); } } @Component public class EventTListener { public EventTListener(){ System.out.println("監(jiān)聽(tīng)器創(chuàng)建"); } } }
利用bean的生命周期中的擴(kuò)展點(diǎn)
@AutoConfigureOrder
@AutoConfigureOrder只能改變外部依賴的@Configuration的順序。
這是不對(duì)的用法
@Slf4j @Configuration @ConfigurationProperties(prefix = "dict") public class SpringConfig { @Component @AutoConfigureOrder(1) public class Event{ public Event(){ System.out.println("事件事件"); } } @Component @AutoConfigureOrder(2) public class EventSource{ public EventSource(Event e){ System.out.println("事件源創(chuàng)建"); } } @Component @AutoConfigureOrder(3) public class EventTListener { public EventTListener(){ System.out.println("監(jiān)聽(tīng)器創(chuàng)建"); } } }
以上內(nèi)容發(fā)現(xiàn),在config里配置是不起作用的。
這是正確的用法
創(chuàng)建兩個(gè)配置類
@Slf4j @Configuration @AutoConfigureOrder(1) public class SpringConfig { @Component public class Event{ public Event(){ System.out.println("首先在SpringConfig"); } } } @Slf4j @Configuration @AutoConfigureOrder(2) public class NewConfig { @Component public class Event{ public Event(){ System.out.println("然后在NewConfig"); } } }
測(cè)試
發(fā)現(xiàn)結(jié)果是不正確的,注解還是沒(méi)有生效。
當(dāng)前工程里增加配置 META-INF/spring.factories,內(nèi)容為項(xiàng)目中的配置類
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sinosoft.springbootplus.common.config.NewConfig,com.sinosoft.springbootplus.common.config.SpringConfig
測(cè)試結(jié)果如圖(正確)
三、遇到的問(wèn)題
需要根據(jù)配置決定生成哪個(gè)實(shí)現(xiàn)類
當(dāng)在配置文件中配置的dict.cacheType的值是local時(shí),初始化LocalISysDictRepository交給spring容器管理;
當(dāng)項(xiàng)目依賴了redis并且配置文件中配置的dict.cacheType的值是redis時(shí),初始化RedisISysDictRepository交給spring容器管理。
但是我又在這兩個(gè)實(shí)現(xiàn)類上加了@Repository注解
也要交給Spring管理,這個(gè)時(shí)候項(xiàng)目啟動(dòng)就報(bào)錯(cuò)了。(通俗的來(lái)說(shuō)一個(gè)類只能一次交給Spring管理)
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用Spring MVC攔截器實(shí)現(xiàn)日志記錄的方法
本篇文章主要介紹了使用Spring MVC攔截器實(shí)現(xiàn)日志記錄的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04手把手教你用Java實(shí)現(xiàn)一套簡(jiǎn)單的鑒權(quán)服務(wù)
現(xiàn)今大部分系統(tǒng)都會(huì)有自己的鑒權(quán)服務(wù),本文介紹了最常用的鑒權(quán)服務(wù),就是日常用戶的登錄登出,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05Java?-jar參數(shù)詳解之掌握J(rèn)ava可執(zhí)行JAR文件的運(yùn)行技巧
做項(xiàng)目的時(shí)候我們肯定接觸過(guò)很多jar包,下面這篇文章主要給大家介紹了關(guān)于Java?-jar參數(shù)詳解之掌握J(rèn)ava可執(zhí)行JAR文件的運(yùn)行技巧,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11java學(xué)生信息管理系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了java學(xué)生信息管理系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01Gradle修改本地倉(cāng)庫(kù)的位置方法實(shí)現(xiàn)
這篇文章主要介紹了Gradle修改本地倉(cāng)庫(kù)的位置方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07SpringBoot返回Json對(duì)象報(bào)錯(cuò)(返回對(duì)象為空{(diào)})
本文主要介紹介紹了SpringBoot返回Json對(duì)象報(bào)錯(cuò)(返回對(duì)象為空{(diào)}),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01java線程并發(fā)countdownlatch類使用示例
javar的CountDownLatch是個(gè)計(jì)數(shù)器,它有一個(gè)初始數(shù),等待這個(gè)計(jì)數(shù)器的線程必須等到計(jì)數(shù)器倒數(shù)到零時(shí)才可繼續(xù)。2014-01-01