springboot如何通過不同的策略動態(tài)調(diào)用不同的實現(xiàn)類
通過不同的策略動態(tài)調(diào)用不同的實現(xiàn)類
經(jīng)常遇到這樣的一個需求,前端傳的實體類型相同,后端需要根據(jù)實體類中的某一個字符串,動態(tài)地調(diào)用某一個類的方法。
在SpringBoot中,我們可以理解成,一個Controller接口對應多個ServiceImpl,使用這種方式,如果后期需要添加一個功能,僅僅創(chuàng)建一個ServiceImpl就可以滿足需求,而不用再額外創(chuàng)建一個Controller接口。
現(xiàn)在假設一個情景,前端傳入不同的用戶類型,后端返回該用戶的任務。
你可能問我,為什么不直接把(用戶類型,用戶任務)存入數(shù)據(jù)庫?
現(xiàn)在只是一個簡單的場景而已,實際中更為復雜,無法直接存入數(shù)據(jù)庫。
代碼演示
我們先定義一個接口
public interface UserService {
//返回用戶的主要任務
String task();
}兩個實現(xiàn)類
@Service("student")
public class StudentServiceImpl implements UserService {
? ? @Override
? ? public String task() {
? ? ? ? return "學習";
? ? }
}@Service("teacher")
public class TeacherServiceImpl implements UserService {
? ? @Override
? ? public String task() {
? ? ? ? return "教書";
? ? }
}實現(xiàn)動態(tài)調(diào)用的核心類
@Service
public class UserContext {?
? ? @Autowired
? ? Map<String, UserService> userMap;
?
? ? public UserService getUserService(String type) {
? ? ? ? return userMap.get(type);
? ? }
}Spring會自動地將形如(@Service后面的名稱,實現(xiàn)該接口的類)注入到該userMap中
在啟動后,userMap中就存在兩個元素,("student",StudentServiceImpl)與("teacher",TeacherServiceImpl)
getUserService方法返回userMap中key=type的UserService對象
實體類
public class User {
private String type;
private String task;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
}Controller層接口
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
UserContext userContext;
@PostMapping("/getTask")
public String getTask(@RequestBody User user) {
UserService userService = userContext.getUserService(user.getType());
return userService.task();
}
}測試樣例:


可能用到的場景舉例
關(guān)于庫存的儀表盤統(tǒng)計
前端傳入?yún)^(qū)域id,倉庫id,物品id等信息
后端依據(jù)參數(shù)動態(tài)地選擇某一個物品實現(xiàn)類,最后返回統(tǒng)計的信息。
這里有幾個問題,為什么不一次性將所有物品id傳入,一次性獲取所有物品的庫存?
一次性傳入,可能后端處理時間邊長,失敗率也高,一旦失敗,整個儀表盤沒有任何數(shù)據(jù)。而且后期可能面臨的一個需求,不同的物品,需要有不同的接口刷新速度,暢銷的物品接口調(diào)用頻率快。所以可能需要將物品分組,一個小組是同一種類型,使用一個實現(xiàn)類。
比如,這里有100種物品,按類型或者其他屬性分成了10組,每個組之間,有一個不同的屬性groupId,但10組共用一個接口,進入接口后,再進入10個不同的實現(xiàn)類,在實現(xiàn)類中調(diào)用具體的計算邏輯。
spring中動態(tài)選擇實現(xiàn)類
在spring中當一個接口有多個實現(xiàn)類的時候,通過創(chuàng)建簡單工廠類,根據(jù)傳入的不同的參數(shù)獲取不同的接口實現(xiàn)類。
public interface ExecuteService {?? ?
?? ?ExecuteEnum getCode();
? ? // 業(yè)務方法
? ? void execute();
}
@Service
public class FirstExecuteServiceImpl implements ExecuteService {?? ?
?? ?@Override
?? ?public ExecuteEnum getCode() {
?? ??? ?return ExecuteEnum.FIRST;
?? ?}
?? ?
?? ?public void execute() {
?? ? ? ?System.out.println("11111111111");
?? ?}
}@Service
public class SecondExecuteServiceImpl implements ExecuteService {?? ?
?? ?@Override
?? ?public ExecuteEnum getCode() {
?? ??? ?return ExecuteEnum.SECOND;
?? ?}
?? ?
?? ?public void execute() {
?? ? ? ?System.out.println("222222222");
?? ?}
}?? ?public enum ExecuteEnum {
?? ??? ?FIRST,
?? ??? ?SECOND,;
?? ?}方案一
@Component
public class ExecuteServiceFactory implements ApplicationContextAware {
?? ?
?? ?private final static Map<ExecuteEnum, ExecuteService> EXECUTE_SERVICES = new HashMap<>();
?? ?@Override
?? ?public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
?? ??? ?Map<String, ExecuteService> types = applicationContext.getBeansOfType(ExecuteService.class);
?? ??? ?types.values().forEach(e -> EXECUTE_SERVICES.putIfAbsent(e.getCode(), e));
?? ?}?? ?
}方案二
@Component
public class ExecuteServiceFactory implements InitializingBean {
? ? @Autowired
? ? private List<ExecuteService> executeServices;
? ? public final static Map<ExecuteEnum, ExecuteService> EXECUTE_SERVICES = new HashMap<>();
? ? @Override
? ? public void afterPropertiesSet() throws Exception {
? ? ? ? executeServices.forEach(l -> EXECUTE_SERVICES.putIfAbsent(l.getCode(), l));
? ? }
}以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
mybatis的映射xml中動態(tài)設置orderby方式
這篇文章主要介紹了mybatis的映射xml中動態(tài)設置orderby方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
Java實戰(zhàn)之基于I/O流設計的圖書管理系統(tǒng)
這篇文章主要介紹了Java實戰(zhàn)之基于I/O流設計的圖書館管理系統(tǒng),文中有非常詳細的代碼示例,對正在學習java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04

