使用Springboot根據配置文件動態註入接口實現類

Springboot根據配置文件動態註入接口實現類

需求

最近在做一個Springboot項目,需要面向不同需求的客戶,但是為瞭方便管理分支,需要將不同客戶的需求都寫到同一套代碼中,根據不同客戶實例化對應的實現類。

實現

為瞭盡量不修改代碼,少做不必要的邏輯判斷,我們考慮為不同客戶寫不同的Service,然後根據配置參數實例化對應的Service。這樣就遇到瞭需要根據配置文件實現不同類的需求。

針對這一需求大致有兩種實現方式。但是針對我的需求,能用的隻有第二種,但還是想將第一種一起總結一下。

兩種方式都需要給定義接口,並針對不同客戶對接口做不同實現。

接口類

public interface IAService {
 
    //獲取客戶名,所有客戶都需要,但是需要針對不同客戶做不同實現
    String getCustomName();
}

針對客戶A和B對上面接口實現兩個類

//註意要給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層寫好以後,需要在Controller層做不同的實現。有兩種方式

1.使用@Qualifier註解

在@Qualifier(“customA”)上標明要實現的類的Service填寫的名字即可。但是這種方式有個弊端。Qualifier註解的參數必須是常量,無法填寫配置文件的值,因此無法使用配置文件動態註入,隻能動手改代碼,基本是雞肋般的存在。

@RestController
public class AController {
 
 
    //如果要給客戶A部署,這裡寫客戶A Service註解的名稱,上面配置的是customA
    @Qualifier("customA")
    IAService iaService;
    
    //不同地區需要有不同的邏輯,下面service實例化的正好是不同地區的實例
    @GetMapping("/name")
    public String getCustomName() {
        return iaService.getCityName();
    }
}

2.使用@Resource註解

上面配置瞭兩個不同客戶Service註解的名稱,我們可以使用Resource註解,通過配置文件的方式進行動態註入。通過配置文件進行靈活切換。

其實代碼並沒有多少改動,僅僅是換成瞭@Resource(name=”${local.name}”)而已,其中的local.name為從配置文件中要讀取的變量對應的值。

@RestController
public class AController {
 
    //根據配置文件中配置的參數決定實例化哪個實現類,解決上面問題1
    @Resource(name="${local.name}")
    IAService iaService;
    
    //不同地區需要有不同的邏輯,下面service實例化的正好是不同地區的實例
    @GetMapping("/name")
    public String getCustomName() {
        return iaService.getCityName();
    }
}

SpringBoot同一接口多個實現類配置

SpringBoot項目中可能出現一個接口有多個實現類的情況,如果不進行配置,註入接口時編譯器不知道要註入哪個實現類就會報錯,因此需要進行配置。

以下進行舉例:

接口如下:

public interface NoticeService {
    public String noticeUser(Long id);
}

兩個實現類如下:

@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;
}

這樣直接啟動後就會報錯,需要在添加@Qualifier註解:

@Controller
@RequestMapping("notice")
public class NoticeController{
 @Autowired
 @Qualifier("impl1")
 NoticeService noticeService;
}

需要調用的實現類中添加標識:

@Service("impl1")
public class NoticeServiceImpl1 implements NoticeService {
 public String noticeUser(Long id){
  return noticeServe1(id);
 }
}

此時再運行即可~

以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。

推薦閱讀: