SpringBoot通过Map实现天然的策略模式

server/2025/3/30 1:36:58/
😊 @ 作者: 一恍过去
💖 @ 主页: https://blog.csdn.net/zhuocailing3390
🎊 @ 社区: Java技术栈交流
🎉 @ 主题: SpringBoot通过Map实现天然的策略模式
⏱️ @ 创作时间: 2025年03月25日

目录

  • 前言
  • 底层机制解析
    • Spring的集合类型自动装配
    • @Resource注解的行为
    • 实现原理
  • 使用
    • 直接使用Map<String,T>
    • 指定Map中的bean类型
      • 定义策略接口
      • 定义实现类
      • 策略使用
      • 验证
    • 自定义注解实现

前言

策略模式是一种行为设计模式,它允许在运行时选择算法的行为。在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式

在Spring框架中,当你使用@Resource注解注入一个Map<String, T>时,Spring会自动将所有类型为T的bean收集到这个Map中,其中:

  • Key是bean的名称
  • Value是bean实例

底层机制解析

Spring的集合类型自动装配

Spring框架对集合类型的依赖注入有特殊处理:

  • 当注入List时,会收集所有类型为T的bean
  • 当注入Map<String, T>时,会收集所有类型为T的bean,并以bean名称作为key

@Resource注解的行为

@Resource注解默认按名称装配,但当目标是一个Map时,Spring会特殊处理:

  • 如果Map的key是String类型,value是某个接口/类
  • Spring会查找所有实现该接口/继承该类的bean
  • 将这些bean以"bean名称->bean实例"的形式放入Map

实现原理

Spring在依赖注入时的处理流程:

  • 发现字段/方法参数是Map<String, T>类型
  • 在应用上下文中查找所有类型为T的bean
  • 创建一个新的Map实例
  • 遍历找到的所有bean,以bean名称作为key,bean实例作为value放入Map
  • 将这个Map注入到目标字段/参数中

使用

直接使用Map<String,T>

我们直接定义一个Controller,并且在Controller中使用@ResourceMap<String,T>

@RestController
@RequestMapping("/test")
public class TestController {@Resourceprivate Map<String, Object> beanMap = new ConcurrentHashMap<>();public void beanMap() {System.out.println(beanMap.size());}
}

验证:
可以看到map中存了项目中所有的bean对象
在这里插入图片描述

指定Map中的bean类型

在实际的开发中,我们希望Map中只是存储需要的Bean,并且Controller中可以根据beanName进行转发到不同的Service中,步骤如下:

定义策略接口

public interface PaymentStrategy {void pay();
}

定义实现类

	@Service("ALI")@Slf4jpublic class AliStrategyService implements PaymentStrategy {@Overridepublic void pay() {log.info("使用支付宝支付");}}@Service("WX")@Slf4jpublic class WxStrategyService implements PaymentStrategy {@Overridepublic void pay() {log.info("使用微信支付");}}

策略使用

@RestController
@RequestMapping("/test")
public class TestController {@Resourceprivate Map<String, PaymentStrategy> beanMap = new ConcurrentHashMap<>();public void beanMap() {PaymentStrategy wx = beanMap.get("WX");wx.pay();PaymentStrategy ali = beanMap.get("ALI");ali.pay();}
}

验证

可以看到map中,就只有两个Bean,并且key就是我们通过@Service(value)定义的名称
在这里插入图片描述
在这里插入图片描述

自定义注解实现

  • 自定义一个注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface PaymentType {String value();
}
  • 注解替换:将原有的@Service(value)替换为@PaymentType (value),比如:
@PaymentType("CARD")
@Slf4j
public class CardStrategyService implements PaymentStrategy {@Overridepublic void pay() {log.info("使用银行卡支付");}
}
  • **意义:**可以更好表示策略模式,让其他开发人员一眼可以看出当前的Service使用了策略模式

在这里插入图片描述


http://www.ppmy.cn/server/179397.html

相关文章

使用请求调用本地部署的stable-diffusion接口

stable-diffusion-webui项目地址 具体部署教程请去B站寻找或者直接使用整合包 这里直接编写工具类 public class StableDiffusionUtil {private static final String BASE_URL "http://127.0.0.1:7860";private static final OkHttpClient CLIENT new OkHttpClien…

在opensuse 系统上安装腾讯会议

需求描述 平常比较习惯使用opensuse 系统&#xff0c;又有远程开会的需求&#xff0c; 所以需要在opensuse 系统上安装腾讯会议。但是需要注意的是&#xff0c;opensuse上面的软件安装包是rpm文件&#xff0c;而腾讯会议的LINUX版本只提供了deb格式的文件&#xff0c;没有办法…

Linux信号:一场内核与用户空间的暗战

在Linux系统的黑暗森林中&#xff0c;每个进程都是小心翼翼的猎人。当一束神秘的信号光划过天际&#xff0c;内核瞬间变身信号调度大师&#xff0c;在进程的生死簿上书写着命运。这场跨越用户空间与内核态的博弈&#xff0c;远比表面看到的更加惊心动魄。 一、 信号诞生的量子…

解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《深度探秘&#xff1a;AI界的007》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、什么是Docker 2、什么是Ollama 二、准备工作 1、操…

七天免登录 为什么不能用seesion,客户端的http请求自动携带cookei的机制(比较重要)涉及HTTP规范

如果是七天免登录,和session肯定没关系,因为session不能持久化,主要是客户端一旦关闭,seesion就失效了/// 所以必须是能持久化的&#xff0c;这就清晰了&#xff0c;要莫在的服务器保存&#xff0c;要摸在客户端设置 cook机制 1. 使用Cookie实现七天免登录 前端&#xff08;登…

专题十三:动态路由——RIP

一、RIP协议简介 Routing Information Protocol&#xff08;路由信息协议&#xff09;的简称&#xff0c;它是一种较为简单的内部网关协议&#xff08;Interior Gateway Protocol&#xff09;。RIP是一种基于距离矢量&#xff08;Distance-Vector&#xff09;算法的协议&#…

拓扑排序(算法基础)

拓扑排序 试想这样一个问题&#xff0c;我们做事情事情本身之间有先决条件。例如我们希望能在这些事情之间找到不破坏依赖关系的前提下对整个结果排序。这被称为拓扑排序。假设下面的例子&#xff0c;每个节点称为一个课程。 #mermaid-svg-klxvcbfYdUg3GXYP {font-family:&quo…

【MySQL | 七、存储引擎是什么?】

存储引擎是什么&#xff1f;作用于哪里&#xff1f; 1. 存储引擎的定义 存储引擎&#xff08;Storage Engine&#xff09;是数据库管理系统中负责 数据的存储、检索和管理 的核心组件。它决定了数据如何存储在磁盘上&#xff0c;以及如何从磁盘中读取数据。存储引擎是数据库与…