SpringBoot业务策略模式多实现类注入过程(Map注入)

 更新时间:2026年06月09日 09:16:19   作者:小胖-Vi  
这段文章主要讨论了在业务处理过程中遇到的登录场景,通过策略模式解决代码冗余和维护困难的问题,具体介绍了策略模式的应用场景、实现方式以及带来的好处,适用于需要根据不同条件选择不同实现逻辑的场景

前言

在业务处理的过程中遇见一个场景,登录分A,B,C,他们都是对应的实现都是增删改查,但是不同的类型对应不同的平台登录方式,同时对应的增删改查业务逻辑有存在差异,这个时候如果不想办法设计代码就会出现A,B,C三种类型都要写一个对应接口(XXXserver),然后分别再去实现他们(XXXserverImpl),如果后来再增加一个平台登录,我们又要去重复相关接口和实现,不仅显得代码冗余,更是不好维护和管理,所以利用设计模式---策略模式就解决了这个问题。

策略模式的引入

一个接口有多个实现

public interface LoginService {


    String passwordSalt = "test";


    /**
     * @param postAccessToken 请求体
     */
    ExecResult<String> prop(Login postAccessToken);

    /**
     * 是否支持特定业务信息的处理
     *
     * @return
     */
    Boolean isSupported(Login postAccessToken);
}
//实现一
@Slf4j
@Service
public class DingdingServiceImpl implements LoginService {



    @Override
    public ExecResult<String> prop(Login postAccessToken) {
 
      System.out.println("钉钉用户");
        return ExecResultUtil.success(JwtUtil.build());
    }

    @Override
    public Boolean isSupported(Login postAccessToken) {
        return Objects.equals(GrantTypeEnum.DINGDING.getCode(), postAccessToken.getGrantType());
    }
}
//实现二
@Service
public class PasswordLoginServiceImpl implements LoginService {


    @Autowired
    private UserAccountService userAccountService;

    @Override
    public ExecResult<String> prop(Login postAccessToken) {
      
      System.out.println("普通用户");
    return ExecResultUtil.success(JwtUtil.build());
    }

    @Override
    public Boolean isSupported(Login postAccessToken) {
        return Objects.equals(GrantTypeEnum.PASSWORD.getCode(), postAccessToken.getGrantType());
    }
}
//实现三
@Service
public class SysPasswordLoginServiceImpl implements LoginService {


    @Autowired
    private UserAccountService userAccountService;

    @Override
    public ExecResult<String> prop(Login postAccessToken) {
       
      System.out.println("系统用户");
return ExecResultUtil.success(JwtUtil.build());
    }

    @Override
    public Boolean isSupported(Login postAccessToken) {
        return Objects.equals(GrantTypeEnum.SYS_PASSWORD.getCode(), postAccessToken.getGrantType());
    }
}

枚举类型

@AllArgsConstructor
public enum GrantTypeEnum {

    PASSWORD("password", "普通用户密码"),
    PHONE("phone", "普通手机验证码"),
    WE_CHAT("wechat", "普通微信"),
    DINGDING("dingding", "普通钉钉"),

    SYS_PASSWORD("sys_password", "系统用户密码"),
    SYS_PHONE("sys_phone", "系统手机验证码"),
    SYS_WE_CHAT("sys_wechat", "系统微信"),
    SYS_DINGDING("sys_dingding", "系统钉钉"),
    ;
    private String code;

    private String message;

    public String getCode() {
        return this.code;
    }

    public String getMessage() {
        return this.message;
    }}

写一个公共的类来判断获取对应的实现类

@Service
public class LoginServiceImpl {

//关键在这个,原理:当一个接口有多个实现类的时候,key为实现类名,value为实现类对象
    private Map<String, LoginService> procMap = new ConcurrentHashMap<>();

    @Autowired(required = false)//这个注入了多个实现类对象
    private List<LoginService> procList = Collections.emptyList();

    public ExecResult<String> prop(Login login) {

        LoginService proc = getProc(login);
        if (null == proc) {
            throw new RuntimeException("no grant type:" + login.getGrantType());
        }
        return proc.prop(login);
    }

    private LoginService getProc(Login grantType) {
        LoginService querier = procMap.get(grantType.getGrantType());
        if (querier != null) {
            return querier;
        }
        for (LoginService item : procList) {
            if (item.isSupported(grantType)) {
                querier = item;
                procMap.put(grantType.getGrantType(), querier);
                return querier;
            }
        }
        return null;
    }

}

控制层(为了测试用,根据业务使用,不一定用在控制层哈)

    @Autowired
    private LoginServiceImpl loginService;


    @ApiOperation(value = "登录")
    @PostMapping("/login")
    public ExecResult<String> postAccessToken(@RequestBody Login login) {
        return loginService.prop(login);
    }

测试

完结撒花 !!!

总结

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

相关文章

  • @DateTimeFormat和@JsonFormat注解的用法及说明

    @DateTimeFormat和@JsonFormat注解的用法及说明

    通过在实体类属性上使用`@DateTimeFormat`和`@JsonFormat`注解,可以实现日期时间格式的入参和出参格式化,确保前端传入的参数能够正确解析,并且后端返回的日期时间格式符合需求
    2025-11-11
  • 关于Java8新特性Optional类的详细解读

    关于Java8新特性Optional类的详细解读

    Optional类是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在,原来用 null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常,需要的朋友可以参考下
    2023-05-05
  • java并发编程之同步器代码示例

    java并发编程之同步器代码示例

    这篇文章主要介绍了java并发编程之同步器代码示例,分享了相关代码,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Java使用RabbitMQ保证消息幂等性的方法步骤

    Java使用RabbitMQ保证消息幂等性的方法步骤

    在Java中使用RabbitMQ时,保证消息处理的幂等性至关重要,幂等性意味着即使同一消息被处理多次,处理的结果也是一致的,本文就来详细的介绍一下Java使用RabbitMQ保证消息幂等性的方法步骤,感兴趣的可以了解一下
    2025-10-10
  • Java 中引入内部类的意义?

    Java 中引入内部类的意义?

    这篇文章主要介绍了Java 中引入内部类的意义?文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,,需要的朋友可以参考下
    2019-06-06
  • SpringBoot集成ElasticSearch实现minio文件内容全文检索

    SpringBoot集成ElasticSearch实现minio文件内容全文检索

    这篇文章详细介绍了如何在Spring Boot项目中集成Elasticsearch和Kibana,包括Docker安装、中文分词器安装、后端代码实现以及前端查询组件封装,需要的朋友可以参考下
    2024-11-11
  • Spring源码剖析之Spring处理循环依赖的问题

    Spring源码剖析之Spring处理循环依赖的问题

    大家都知道循环依赖依赖指的是Bean与Bean之间的依赖关系,循环依赖指的是两个或者多个Bean相互依赖,本文通过代码示例给大家讲解Spring处理循环依赖的问题,感兴趣的朋友一起看看吧
    2021-06-06
  • Java二叉树路径和代码示例

    Java二叉树路径和代码示例

    这篇文章主要介绍了Java二叉树路径和代码示例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • mybatis插入一条数据返回相应数据ID问题及解决

    mybatis插入一条数据返回相应数据ID问题及解决

    MyBatis插入数据并获取自增ID的方法,通过设置useGeneratedKeys=true和keyProperty属性,可以自动将生成的ID赋值给实体对象的相应属性
    2026-05-05
  • Spring 整合Shiro 并扩展使用EL表达式的实例详解

    Spring 整合Shiro 并扩展使用EL表达式的实例详解

    Shiro是一个轻量级的权限控制框架,应用非常广泛。本文的重点是介绍Spring整合Shiro,并通过扩展使用Spring的EL表达式。需要的朋友可以参考下
    2018-03-03

最新评论