Contents

SpringBoot dynamically calls different implementation classes through different strategies

前言

有这样的一个需求,前端传的实体类型相同,后端需要根据实体类中的某一个字符串,动态地调用某一个类的方法。

在SpringBoot中,可以理解成,一个Controller接口对应多个ServiceImpl,使用这种方式,如果后期需要添加一个功能,仅仅创建一个ServiceImpl就可以满足需求,而不用再额外创建一个Controller接口。

代码演示

现在假设一个情景,前端传入不同的用户类型,后端返回该用户的任务。

定义一个接口

1
2
3
4
public interface UserService {
    //返回用户的主要任务
    String task();
}

两个实现类

1
2
3
4
5
6
7
@Service("student")
public class StudentServiceImpl implements UserService {
    @Override
    public String task() {
        return "学习";
    }
}
1
2
3
4
5
6
7
@Service("teacher")
public class TeacherServiceImpl implements UserService {
    @Override
    public String task() {
        return "教书";
    }
}

实现动态调用的核心类

1
2
3
4
5
6
7
8
9
@Service
public class UserContext {
    @Autowired
    Map<String, UserService> userMap;
 
    public UserService getUserService(String type) {
        return userMap.get(type);
    }
}

Spring会自动地将形如(@Service后面的名称,实现该接口的类)注入到该userMap

在启动后,userMap中就存在两个元素,

  • (“student”,StudentServiceImpl)
  • (“teacher”,TeacherServiceImpl)

getUserService方法返回userMap中key=typeUserService对象

实体类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
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层接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@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();
    }
}

测试样例

type为学生时:

/images/2022-09-05-SpringBoot通过不同的策略动态调用不同的实现类/1

type为老师时:

/images/2022-09-05-SpringBoot通过不同的策略动态调用不同的实现类/2

总结

可能用到的场景举例:

关于库存的仪表盘统计:

前端传入区域id,仓库id,物品id等信息

后端依据参数动态地选择某一个物品实现类,最后返回统计的信息

本文所有代码都放在了github上,clone下来即可运行查看效果!