springboot如何通过不同的策略动态调用不同的实现类

目录
  • 通过不同的策略动态调用不同的实现类
    • 代码演示
    • 可能用到的场景举例
  • spring中动态选择实现类
    • 方案一
    • 方案二

通过不同的策略动态调用不同的实现类

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

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

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

你可能问我,为什么不直接把(用户类型,用户任务)存入数据库?

现在只是一个简单的场景而已,实际中更为复杂,无法直接存入数据库。

代码演示

我们先定义一个接口

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

两个实现类

@Service("student")
public class StudentServiceImpl implements UserService {
    @Override
    public String task() {
        return "学习";
    }
}
@Service("teacher")
public class TeacherServiceImpl implements UserService {
    @Override
    public String task() {
        return "教书";
    }
}

实现动态调用的核心类

@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=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();
    }
}

测试样例:

可能用到的场景举例

关于库存的仪表盘统计

前端传入区域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<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));
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot同一接口多个实现类配置的实例详解

    SpringBoot项目中可能出现一个接口有多个实现类的情况,如果不进行配置,注入接口时编译器不知道要注入哪个实现类就会报错,因此需要进行配置.以下进行举例: 接口如下: public interface NoticeService { public String noticeUser(Long id); } 两个实现类如下: @Service public class NoticeServiceImpl1 implements NoticeService { public String not

  • 使用Springboot根据配置文件动态注入接口实现类

    Springboot根据配置文件动态注入接口实现类 需求 最近在做一个Springboot项目,需要面向不同需求的客户,但是为了方便管理分支,需要将不同客户的需求都写到同一套代码中,根据不同客户实例化对应的实现类. 实现 为了尽量不修改代码,少做不必要的逻辑判断,我们考虑为不同客户写不同的Service,然后根据配置参数实例化对应的Service.这样就遇到了需要根据配置文件实现不同类的需求. 针对这一需求大致有两种实现方式.但是针对我的需求,能用的只有第二种,但还是想将第一种一起总结一下. 两

  • Springboot实现根据条件切换注入不同实现类的示例代码

    最近有个一需求需要根据外界环境的属性(操作系统 || yml属性 || 其他bean的状态) 来实现启动时注入两套不同的实现类, 实现切换. 实现启动时条件注入分2步: 第一步 使用@Conditional(参数为 True false条件实现类 需要你自己实现)注解 @Conditional(RabbitMqCondition.class) public class RabbitmqSMSMsgServiceImpl extends RabbitmqBasicMsgService { // @

  • springboot动态调用实现类方式

    目录 springboot动态调用实现类 springboot手动获取实现类 springboot动态调用实现类 定义规则的多种类型 /** * 数据规则处理类型枚举 */ public enum RuleType { MYRULEBYID1, MYRULEBYID2 } 接口 import java.util.List; import java.util.Map; public interface DataRuleParse { /** * 获取规则处理的类型 * @return */ Rul

  • springboot如何通过不同的策略动态调用不同的实现类

    目录 通过不同的策略动态调用不同的实现类 代码演示 可能用到的场景举例 spring中动态选择实现类 方案一 方案二 通过不同的策略动态调用不同的实现类 经常遇到这样的一个需求,前端传的实体类型相同,后端需要根据实体类中的某一个字符串,动态地调用某一个类的方法. 在SpringBoot中,我们可以理解成,一个Controller接口对应多个ServiceImpl,使用这种方式,如果后期需要添加一个功能,仅仅创建一个ServiceImpl就可以满足需求,而不用再额外创建一个Controller接口

  • SpringBoot整合MQTT并实现异步线程调用的问题

    目录 为什么选择MQTT 使用背景 代码实现 基础代码 异步线程处理实现 为什么选择MQTT MQTT的定义相信很多人都能讲的头头是道,本文章也不讨论什么高大上的东西,旨在用最简单直观的方式让每一位刚接触的同行们可以最快的应用起来 先从使用MQTT需要什么开始分析: 消息服务器 不同应用/设备之间的频繁交互 可能涉及一对多的消息传递 基于SpringBoot通过注解实现对mqtt消息处理的异步调用 使用背景 生产环境下, 由于mqtt 生产者生产的消息逐渐增多, 可能会导致消息堆积. 因此需要消

  • Springboot实现根据用户ID切换动态数据源

    首先在application.yml 文件添加一下配置  #每个库可连接最大用户数 dynamic-server: #每个服务最大建库数 database-max-number: 30 #每个库最大用户连接数 user-max-number: 200 template: gis_template 然后项目中添加 dynamicds 模块的代码,仅展示模块文件目录,代码太多不展示了 然后添加拦截器 @Override public void addInterceptors(InterceptorR

  • SpringBoot整合SpringSecurityOauth2实现鉴权动态权限问题

    目录 写在前面 准备 效果展示 实现 写在前面 思考:为什么需要鉴权呢? 系统开发好上线后,API接口会暴露在互联网上会存在一定的安全风险,例如:爬虫.恶意访问等.因此,我们需要对非开放API接口进行用户鉴权,鉴权通过之后再允许调用. 准备 spring-boot:2.1.4.RELEASE spring-security-oauth2:2.3.3.RELEASE(如果要使用源码,不要随意改动这个版本号,因为2.4往上的写法不一样了) mysql:5.7 效果展示 这边只用了postman做测试

  • 通过java反射机制动态调用某方法的总结(推荐)

    如下: public Object invokeMethod(String className, String methodName, Object[] args) throws Exception{ Class ownerClass = Class.forName(className); Object owner = ownerClass.newInstance(); Class[] argsClass = new Class[args.length]; for (int i = 0, j =

  • Java的反射机制---动态调用对象的简单方法

    唉!我还真是在面试中学习新东东啊,一个公司刚刚给了个测试,不过我很奇怪的是为什么web developer的职位居然考java的反射机制题,不过学习研究一下反射机制对我来说是件好事啦! 先说说什么是java反射机制吧,在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这 种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.主要功能:在运行时判断任意一个对象所属的类:在运行时构造任意一个类的对 象:在运行时判断任意一个

  • .NET CORE动态调用泛型方法详解

    本文实例为大家分享了.NET CORE动态调用泛型方法,供大家参考,具体内容如下 using System; using System.Reflection; namespace DynamicCall { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); Program p = new Program(); var ti = p.GetType().GetTypeI

  • C# .Net动态调用webService实现思路及代码

    复制代码 代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Net; using System.IO; using System.Web.Services.Description; using System.CodeDom; using Microsoft.CSharp; using System.CodeDom.Compiler; usi

  • php中的动态调用实例分析

    本文实例讲述了php中的动态调用具体用法.分享给大家供大家参考.具体分析如下: 在程序中如果加一大堆判断的确是一个很大的麻烦,例如这样: 复制代码 代码如下: if($fun='a'){echo "哎呀!";} elesif(){} -- else{echo "嗯!";} 真的很麻烦并且造成程序后期阅读和修改时候的巨大麻烦,这时候我们可以把每一个要执行的代码段,用函数来实现,然后可以用一个更加NB的方法来实现这些功能,并且因为每一个函数实现一个功能,我们维护起来就简

随机推荐