springboot接口多實(shí)現(xiàn)類選擇性注入解決方案
一、問題的描述
在實(shí)際的系統(tǒng)應(yīng)用開發(fā)中我經(jīng)常會(huì)遇到這樣的一類需求,相信大家在工作中也會(huì)經(jīng)常遇到:
同一個(gè)系統(tǒng)在多個(gè)省份部署。
一個(gè)業(yè)務(wù)在北京是一種實(shí)現(xiàn)方式,是基于北京用戶的需求。
同樣的業(yè)務(wù)在上海是另外一種實(shí)現(xiàn)方式,與北京的實(shí)現(xiàn)方式大同小異
遇到這樣的需求,我們通常會(huì)定義一個(gè)業(yè)務(wù)實(shí)現(xiàn)的接口,比如:
public interface IDemoService { public void doSomething(); }
在北京環(huán)境下這樣實(shí)現(xiàn),比如:
@Component public class DemoServiceBeijing implements IDemoService { @Override public void doSomething() {System.out.println("北京的業(yè)務(wù)實(shí)現(xiàn)");} }
在上海環(huán)境下這樣實(shí)現(xiàn),比如:
@Component public class DemoServiceShanghai implements IDemoService { @Override public void doSomething() {System.out.println("上海的業(yè)務(wù)實(shí)現(xiàn)");} }
然后我們寫一個(gè)模擬業(yè)務(wù)測(cè)試用例
@SpringBootTest class DemoApplicationTests { //這里注入的demoService是DemoServiceShanghai,還是DemoServiceBeijing? @Resource IDemoService demoService; @Test void testDemoService() { demoService.doSomething(); } }
當(dāng)我們執(zhí)行這個(gè)測(cè)試用例的時(shí)候一定會(huì)報(bào)錯(cuò),因?yàn)镾pring發(fā)現(xiàn)了兩個(gè)IDemoService的實(shí)現(xiàn)類。它不知道去實(shí)例化哪一個(gè)實(shí)現(xiàn)類,來作為IDemoService的實(shí)際業(yè)務(wù)處理bean。當(dāng)然我們期望的狀態(tài)是:
在北京部署系統(tǒng)的時(shí)候,使用DemoServiceBeijing作為IDemoService的實(shí)現(xiàn)類完成依賴注入
在上海部署系統(tǒng)的時(shí)候,使用DemoServiceShanghai作為IDemoService的實(shí)現(xiàn)類完成依賴注入
二、相對(duì)低級(jí)解決方案
面對(duì)上面的需求,先說幾個(gè)相對(duì)低級(jí)的解決方案,這幾個(gè)方案雖然可以實(shí)現(xiàn)我們期望的狀態(tài),但是對(duì)運(yùn)維不夠友好。
2.1. 方案一:使用@Primary注解
假如在北京部署系統(tǒng)的時(shí)候,在DemoServiceBeijing的類上面加上@Primary
,該注解的作用就是強(qiáng)迫從多個(gè)實(shí)現(xiàn)類里面選一個(gè)實(shí)現(xiàn)類,如果Spring不知道選哪一個(gè),我們告訴它一個(gè)默認(rèn)的。
2.2. 方案二:使用@Resource注解
因?yàn)?code>@Resource注解默認(rèn)使用名稱進(jìn)行依賴注入,所以變量名明確叫做demoServiceBeijing(首字母小寫),使用的就是DemoServiceBeijing實(shí)現(xiàn)類。
@Resource IDemoService demoServiceBeijing; //這里的變量名稱指定了bean名稱 //IDemoService demoService; 被替換掉
或者
@Resource(name = "demoServiceBeijing") //使用resource注解明確指定名稱 IDemoService demoService;
2.3.方案三:使用@Qualifier注解
與上文同樣的道理,使用@Qualifier
注解,指定bean的名稱進(jìn)行依賴注入
@Qualifier("demoServiceBeijing") //使用Qualifier注解明確指定名稱 @Resource IDemoService demoService;
上面所提到的三個(gè)方案雖然都可以解決:在不同的部署環(huán)境下使用不同的接口實(shí)現(xiàn)類完成依賴注入的問題。但是這樣不好,因?yàn)橐坏┪覀円巡渴瓠h(huán)境從beijing(北京)換成shanghai(上海),就需要把上面的注解的位置或者內(nèi)容全都修改一遍(所有的實(shí)現(xiàn)類代碼都要修改)。
三、相對(duì)高級(jí)的解決方案
我們提出進(jìn)一步的期望:就是只修改一個(gè)配置就能完成部署環(huán)境切換的操作。比如:
deploy: province: beijing
當(dāng)我們期望把部署環(huán)境從北京切換到上海的時(shí)候,只需要將上文配置中的beijing 改成 shanghai ,這該怎么實(shí)現(xiàn)呢?
在北京的實(shí)現(xiàn)類上面加上ConditionalOnProperty注解,havingValue的值為beijing
@Component @ConditionalOnProperty(value="deploy.province",havingValue = "beijing") public class DemoServiceBeijing implements IDemoService {
在上海的實(shí)現(xiàn)類上面加上ConditionalOnProperty注解,havingValue的值為shanghai
@Component @ConditionalOnProperty(value="deploy.province",havingValue = "shanghai") public class DemoServiceShanghai implements IDemoService {
ConditionalOnProperty注解在這里的作用就是:讀取配置文件發(fā)現(xiàn)deploy.province
,并將該配置的值與havingValue匹配,匹配上哪一個(gè)就實(shí)例化哪一個(gè)類作為該接口的實(shí)現(xiàn)類bean注入到Spring容器中(當(dāng)然注入過程需要配合@Component
注解實(shí)現(xiàn))
以上就是springboot接口多實(shí)現(xiàn)類選擇性注入解決方案的詳細(xì)內(nèi)容,更多關(guān)于springboot接口多實(shí)現(xiàn)類選擇性注入的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot頂層接口實(shí)現(xiàn)類注入項(xiàng)目的方法示例
- SpringBoot通過Filter實(shí)現(xiàn)整個(gè)項(xiàng)目接口的SQL注入攔截詳解
- Springboot根據(jù)配置文件動(dòng)態(tài)注入接口實(shí)現(xiàn)類詳解
- 使用SpringBoot根據(jù)配置注入接口的不同實(shí)現(xiàn)類(代碼演示)
- SpringBoot使用@Autowired為多實(shí)現(xiàn)的接口注入依賴
- 使用Springboot根據(jù)配置文件動(dòng)態(tài)注入接口實(shí)現(xiàn)類
- SpringBoot中多個(gè)實(shí)現(xiàn)的接口正確注入的六種方式
相關(guān)文章
Feign遠(yuǎn)程調(diào)用丟失請(qǐng)求頭問題
本文介紹了在服務(wù)端項(xiàng)目中如何解決資源訪問限制問題,首先介紹了問題的產(chǎn)生,然后詳細(xì)解析了源碼,最后提出了解決方案,解決方案包括同步和異步兩種,同步時(shí)直接向Spring容器注入RequestInterceptor攔截器2024-09-09springboot+thymeleaf+shiro標(biāo)簽的實(shí)例
這篇文章主要介紹了springboot+thymeleaf+shiro標(biāo)簽的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01springboot集成mybatis?plus和dynamic-datasource注意事項(xiàng)說明
這篇文章主要介紹了springboot集成mybatis?plus和dynamic-datasource注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01淺談SpringBoot內(nèi)嵌Tomcat的實(shí)現(xiàn)原理解析
這篇文章主要介紹了淺談SpringBoot內(nèi)嵌Tomcat的實(shí)現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12servlet的url-pattern匹配規(guī)則詳細(xì)描述(小結(jié))
在利用servlet或Filter進(jìn)行url請(qǐng)求的匹配時(shí),很關(guān)鍵的一點(diǎn)就是匹配規(guī)則。這篇文章主要介紹了servlet的url-pattern匹配規(guī)則詳細(xì)描述(小結(jié)),非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-07-07Java自定義簡(jiǎn)單標(biāo)簽實(shí)例
Java自定義簡(jiǎn)單標(biāo)簽可以方便的在頁面輸出信息,并且對(duì)于權(quán)限的控制,和對(duì)于Jsp標(biāo)簽和servlet代碼的分離有著很好的作用2013-07-07Springboot中useGeneratedKeys用法小結(jié)
本文主要介紹了Springboot中useGeneratedKeys用法小結(jié),useGeneratedKeys?是 MyBatis 框架中的一個(gè)參數(shù),用于指定是否允許 JDBC 支持自動(dòng)生成主鍵,感興趣的可以了解一下2024-09-09