使用Springboot根據(jù)配置文件動(dòng)態(tài)注入接口實(shí)現(xiàn)類
Springboot根據(jù)配置文件動(dòng)態(tài)注入接口實(shí)現(xiàn)類
需求
最近在做一個(gè)Springboot項(xiàng)目,需要面向不同需求的客戶,但是為了方便管理分支,需要將不同客戶的需求都寫(xiě)到同一套代碼中,根據(jù)不同客戶實(shí)例化對(duì)應(yīng)的實(shí)現(xiàn)類。
實(shí)現(xiàn)
為了盡量不修改代碼,少做不必要的邏輯判斷,我們考慮為不同客戶寫(xiě)不同的Service,然后根據(jù)配置參數(shù)實(shí)例化對(duì)應(yīng)的Service。這樣就遇到了需要根據(jù)配置文件實(shí)現(xiàn)不同類的需求。
針對(duì)這一需求大致有兩種實(shí)現(xiàn)方式。但是針對(duì)我的需求,能用的只有第二種,但還是想將第一種一起總結(jié)一下。
兩種方式都需要給定義接口,并針對(duì)不同客戶對(duì)接口做不同實(shí)現(xiàn)。
接口類
public interface IAService { //獲取客戶名,所有客戶都需要,但是需要針對(duì)不同客戶做不同實(shí)現(xiàn) String getCustomName(); }
針對(duì)客戶A和B對(duì)上面接口實(shí)現(xiàn)兩個(gè)類
//注意要給Service命名 @Service("customA") public class IAServiceShijiazhuangImpl implements IAService{ //A客戶的邏輯 @Override public String getCustomName() { return "客戶A"; } } //注意要給Service命名 @Service("customB") public class IAServiceLinyiImpl implements IAService{ //客戶B的邏輯 @Override public String getCityName() { return "客戶B"; } }
Service層寫(xiě)好以后,需要在Controller層做不同的實(shí)現(xiàn)。有兩種方式
1.使用@Qualifier注解
在@Qualifier("customA")上標(biāo)明要實(shí)現(xiàn)的類的Service填寫(xiě)的名字即可。但是這種方式有個(gè)弊端。Qualifier注解的參數(shù)必須是常量,無(wú)法填寫(xiě)配置文件的值,因此無(wú)法使用配置文件動(dòng)態(tài)注入,只能動(dòng)手改代碼,基本是雞肋般的存在。
@RestController public class AController { //如果要給客戶A部署,這里寫(xiě)客戶A Service注解的名稱,上面配置的是customA @Qualifier("customA") IAService iaService; //不同地區(qū)需要有不同的邏輯,下面service實(shí)例化的正好是不同地區(qū)的實(shí)例 @GetMapping("/name") public String getCustomName() { return iaService.getCityName(); } }
2.使用@Resource注解
上面配置了兩個(gè)不同客戶Service注解的名稱,我們可以使用Resource注解,通過(guò)配置文件的方式進(jìn)行動(dòng)態(tài)注入。通過(guò)配置文件進(jìn)行靈活切換。
其實(shí)代碼并沒(méi)有多少改動(dòng),僅僅是換成了@Resource(name="${local.name}")而已,其中的local.name為從配置文件中要讀取的變量對(duì)應(yīng)的值。
@RestController public class AController { //根據(jù)配置文件中配置的參數(shù)決定實(shí)例化哪個(gè)實(shí)現(xiàn)類,解決上面問(wèn)題1 @Resource(name="${local.name}") IAService iaService; //不同地區(qū)需要有不同的邏輯,下面service實(shí)例化的正好是不同地區(qū)的實(shí)例 @GetMapping("/name") public String getCustomName() { return iaService.getCityName(); } }
SpringBoot同一接口多個(gè)實(shí)現(xiàn)類配置
SpringBoot項(xiàng)目中可能出現(xiàn)一個(gè)接口有多個(gè)實(shí)現(xiàn)類的情況,如果不進(jìn)行配置,注入接口時(shí)編譯器不知道要注入哪個(gè)實(shí)現(xiàn)類就會(huì)報(bào)錯(cuò),因此需要進(jìn)行配置。
以下進(jìn)行舉例:
接口如下:
public interface NoticeService { public String noticeUser(Long id); }
兩個(gè)實(shí)現(xiàn)類如下:
@Service public class NoticeServiceImpl1 implements NoticeService { public String noticeUser(Long id){ return noticeServe1(id); } }
@Service public class NoticeServiceImpl2 implements NoticeService { public String noticeUser(Long id){ return noticeServe2(id); } }
Controller如下:
@Controller @RequestMapping("notice") public class NoticeController{ @Autowired NoticeService noticeService; }
這樣直接啟動(dòng)后就會(huì)報(bào)錯(cuò),需要在添加@Qualifier注解:
@Controller @RequestMapping("notice") public class NoticeController{ @Autowired @Qualifier("impl1") NoticeService noticeService; }
需要調(diào)用的實(shí)現(xiàn)類中添加標(biāo)識(shí):
@Service("impl1") public class NoticeServiceImpl1 implements NoticeService { public String noticeUser(Long id){ return noticeServe1(id); } }
此時(shí)再運(yùn)行即可~
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot頂層接口實(shí)現(xiàn)類注入項(xiàng)目的方法示例
- SpringBoot通過(guò)Filter實(shí)現(xiàn)整個(gè)項(xiàng)目接口的SQL注入攔截詳解
- Springboot根據(jù)配置文件動(dòng)態(tài)注入接口實(shí)現(xiàn)類詳解
- 使用SpringBoot根據(jù)配置注入接口的不同實(shí)現(xiàn)類(代碼演示)
- springboot接口多實(shí)現(xiàn)類選擇性注入解決方案
- SpringBoot使用@Autowired為多實(shí)現(xiàn)的接口注入依賴
- SpringBoot中多個(gè)實(shí)現(xiàn)的接口正確注入的六種方式
相關(guān)文章
springboot mybatis-plus實(shí)現(xiàn)登錄接口
本文主要介紹了springboot mybatis-plus實(shí)現(xiàn)登錄接口,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11Springboot實(shí)現(xiàn)多服務(wù)器session共享
這篇文章主要為大家詳細(xì)介紹了Springboot實(shí)現(xiàn)多服務(wù)器session共享,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05SpringMVC框架和SpringBoot項(xiàng)目中控制器的響應(yīng)結(jié)果深入分析
這篇文章主要介紹了SpringMVC框架和SpringBoot項(xiàng)目中控制器的響應(yīng)結(jié)果,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12Spring Boot使用模板freemarker的示例代碼
本篇文章主要介紹了Spring Boot使用模板freemarker的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10深入理解Java動(dòng)態(tài)代理與靜態(tài)代理
這篇文章主要介紹了深入理解Java動(dòng)態(tài)代理與靜態(tài)代理,靜態(tài)代理,代理類和被代理的類實(shí)現(xiàn)了同樣的接口,代理類同時(shí)持有被代理類的引用,動(dòng)態(tài)代理的根據(jù)實(shí)現(xiàn)方式的不同可以分為JDK動(dòng)態(tài)代理和CGlib動(dòng)態(tài)代理2022-06-06jstl之map,list訪問(wèn)遍歷以及el表達(dá)式map取值的實(shí)現(xiàn)
下面小編就為大家?guī)?lái)一篇jstl之map,list訪問(wèn)遍歷以及el表達(dá)式map取值的實(shí)現(xiàn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03Spring Boot中使用JDBC Templet的方法教程
這篇文章主要給大家介紹了關(guān)于在Spring Boot中使用JDBC Templet的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03