洞察探索open banking如何通过小程序容器技术助力金融企业实现数据安全和数字化转型
2025
2022-10-26
springboot如何通过不同的策略动态调用不同的实现类
目录通过不同的策略动态调用不同的实现类代码演示可能用到的场景举例spring中动态选择实现类方案一方案二
通过不同的策略动态调用不同的实现类
经常遇到这样的一个需求,前端传的实体类型相同,后端需要根据实体类中的某一个字符串,动态地调用某一个类的方法。
在SpringBoot中,我们可以理解成,一个Controller接口对应多个ServiceImpl,使用这种方式,如果后期需要添加一个功能,仅仅创建一个ServiceImpl就可以满足需求,而不用再额外创建一个Controller接口。
现在假设一个情景,前端传入不同的用户类型,后端返回该用户的任务。
你可能问我,为什么不直接把(用户类型,用户任务)存入数据库?
现在只是一个简单的场景而已,实际中更为复杂,无法直接存入数据库。
代码演示
我们先定义一个接口
public interface UserService {
//返回用户的主要任务
String task();
}
两个实现类
@Service("student")
public class StudentServiceImpl implemenhttp://ts UserService {
@Override
public String task() {
return "学习";
}
}
@Service("teacher")
public class TeacherServiceImpl implements UserService {
@Override
publhttp://ic String task() {
return "教书";
}
}
实现动态调用的核心类
@Service
public class UserContext {
@Autowired
Map
public UserService getUserService(String type) {
return userMap.get(type);
}
}
Spring会自动地将形如(@Service后面的名称,实现该接口的类)注入到该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 MEnBybQmOgetTask(@RequestBody User user) {
UserService userService = userContext.getUserService(user.getType());
return userService.task();
}
}
测试样例:
可能用到的场景举例
关于库存的仪表盘统计
前端传入区域id,仓库id,物品id等信息
后端依据参数动态地选择某一个物品实现类,最后返回统计的信息。
这里有几个问题,为什么不一次性将所有物品id传入,一次性获取所有物品的库存?
一次性传入,可能后端处理时间边长,失败率也高,一旦失败,整个仪表盘没有任何数据。而且后期可能面临的一个需求,不同的物品,需要有不同的接口刷新速度,畅销的物品接口调用频率快。所以可能需要将物品分组,一个小组是同一种类型,使用一个实现类。
比如,这里有100种物品,按类型或者其他属性分成了10组,每个组之间,有一个不同的属性groupId,但10组共用一个接口,进入接口后,再进入10个不同的实现类,在实现类中调用具体的计算逻辑。
spring中动态选择实现类
在spring中当一个接口有多个实现类的时候,通过创建简单工厂类,根据传入的不同的参数获取不同的接口实现类。
public interface ExecuteService {
ExecuteEnum getCode();
// 业务方法
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
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map types.values().forEach(e -> EXECUTE_SERVICES.putIfAbsent(e.getCode(), e)); } } 方案二 @Component public class ExecuteServiceFactory implements InitializingBean { @Autowired private List public final static Map @Override public void afterPropertiesSet() throws Exception { executeServices.forEach(l -> EXECUTE_SERVICES.putIfAbsent(l.getCode(), l)); } }
types.values().forEach(e -> EXECUTE_SERVICES.putIfAbsent(e.getCode(), e));
}
}
方案二
@Component
public class ExecuteServiceFactory implements InitializingBean {
@Autowired
private List
public final static Map
@Override
public void afterPropertiesSet() throws Exception {
executeServices.forEach(l -> EXECUTE_SERVICES.putIfAbsent(l.getCode(), l));
}
}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~