策略模式环境类的实现方式对比

server/2025/2/27 13:42:47/

文章目录

  • 1、策略模式
  • 2、聚合策略类实现方式一
  • 3、聚合策略类实现方式二
  • 4、对比
  • 5、补充:ApplicationContextAware接口

1、策略模式

近期工作中,需要处理4.x和5.x两个版本的数据,所以自然想到的是策略模式,写一个抽象类,然后两个版本分别实现抽象类,以后也好扩展。

public interface ClusterMetaDataProcessor {void processData();}
public class Version4ClusterMetaDataProcessor implements ClusterMetaDataProcessor {@Overridevoid processData() {//...}
}
public class Version5ClusterMetaDataProcessor implements ClusterMetaDataProcessor {@Overridevoid processData() {//...}
}

然后写个聚合策略类,或者叫环境类,给调用者统一使用,此时有两种实现方式,如下

2、聚合策略类实现方式一

使用ApplicationContextAware接口获取实现类的Bean对象:

@Component
public class MetaDataProcessorFactory implements ApplicationContextAware {private final Map<String, ClusterMetaDataProcessor> PROCESSOR_MAP = new ConcurrentHashMap<>();public ClusterMetaDataProcessor getProcessor(String version) {ClusterMetaDataProcessor processor = PROCESSOR_MAP.get(version);if (processor == null) {throw new RuntimeException("Unknown version: " + version);}return processor;}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {PROCESSOR_MAP.put("4.x", applicationContext.getBean(Version4ClusterMetaDataProcessor.class));PROCESSOR_MAP.put("5.x", applicationContext.getBean(Version5ClusterMetaDataProcessor.class));}}

3、聚合策略类实现方式二

这种方式,实现的核心是自动装配,当 Spring 处理 @Bean 方法的参数时,若参数类型为 List<T>,容器会自动扫描所有​类型是 T 或其子类的Bean,所有符合条件的 Bean 会被收集到 List 中,注入顺序与 Bean 的定义顺序一致​(可通过 @Order 注解或配置文件调整),以后要新增6.x的处理器逻辑,只需新增实现 ClusterMetaDataProcessor 的 Bean,无需修改现有的代码,符合开闭原则


@Configuration
public class MetaDataProcessorFactory {@Bean(name = "clusterMetaDataProcessorMap")public Map<String, ClusterMetaDataProcessor> clusterMetaDataProcessorMap(List<ClusterMetaDataProcessor> processorList) {Map<String, ClusterMetaDataProcessor> processorMap = new HashMap<>();for (ClusterMetaDataProcessor processor : processorList) {if (processorMap.put(processor.getVersion(), processor) != null) {throw new IllegalStateException("Duplicate key for cluster metadata processor: " + processor.getVersion());}}return processorMap;}}

在Service层代码中注入这个Map,使用@Qualifier指定前面定义时起的Bean的名字即可:

@Service
public class ServiceA {private final Map<String, ClusterMetaDataProcessor> clusterMetaDataProcessorMap;public ServiceA(@Qualifier("clusterMetaDataProcessorMap") Map<String, ClusterMetaDataProcessor> clusterMetaDataProcessorMap) {this.clusterMetaDataProcessorMap = clusterMetaDataProcessorMap;}
}

4、对比

特性​​@Bean + List<T>方案​手动注册方案(ApplicationContextAware)​​
​扩展性​支持动态新增处理器版本需手动修改代码注册新版本
​代码简洁性​ 更简洁,无需实现接口代码冗长,需手动管理版本号

5、补充:ApplicationContextAware接口

实现ApplicationContextAware接口,重写setApplicationContext方法,setApplicationContext方法的执行时机:

  • Spring 容器首先会根据配置(XML/注解)实例化 Bean 对象
  • 然后完成该 Bean 的属性注入(例如通过 @Autowired 或 XML 的 <property> 标签注入的其他 Bean)
  • 此时,如果该 Bean 实现了 ApplicationContextAware 接口,容器就会调用 setApplicationContext 方法
  • 最后再是@PostConstruct、自定义的 init-method等初始化Bean的操作

简单说就是:

1. 实例化 Bean 对象
2. 执行依赖注入(设置字段值)
3. 调用 `setApplicationContext` (如果 Bean 实现 ApplicationContextAware)
4. 执行初始化回调(如 @PostConstruct / init-method)
5. Bean 可用(被其他 Bean 引用)

举个例子:

@Component
public class MyBean implements ApplicationContextAware {@Overridepublic void setApplicationContext(ApplicationContext context) throws BeansException {// 此时可以立即使用 context 获取其他 BeanMyService service = context.getBean(MyService.class);}
}

当 Spring 容器启动时,MyBean 会被实例化 → 注入依赖 → 调用 setApplicationContext → 最后执行初始化方法


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

相关文章

PySpark实现Snowflake数据导出到Amazon Redshift

编写AWS EMR上的高性能PySpark代码&#xff0c;实现用SQL从Snowflake上下载数据到S3里的parquet文件&#xff0c;并导入Redshift表。 步骤一&#xff1a;配置EMR集群 首先确保您已经在AWS EMR上正确地设置了包含适当权限的角色和安全组的集群。该角色应允许访问Snowflake数据…

Python 基本语法的详细解释

目录 &#xff08;1&#xff09;注释 &#xff08;2&#xff09;缩进 &#xff08;3&#xff09;变量和数据类型 变量定义 数据类型 &#xff08;4&#xff09;输入和输出 输出&#xff1a;print() 函数 输入&#xff1a;input() 函数 &#xff08;1&#xff09;注释 注…

如何最小化Spark中的Shuffle开销

在Spark中&#xff0c;Shuffle是指数据在不同节点之间重新分配的过程&#xff0c;这个过程通常会涉及大量的数据传输和磁盘读写&#xff0c;消耗大量的计算和网络资源&#xff0c;因此是Spark作业中的一个性能瓶颈。为了最小化Spark中的Shuffle开销&#xff0c;可以采取以下策略…

智慧物流小程序(论文源码调试讲解)

第4章 系统设计 一个成功设计的系统在内容上必定是丰富的&#xff0c;在系统外观或系统功能上必定是对用户友好的。所以为了提升系统的价值&#xff0c;吸引更多的访问者访问系统&#xff0c;以及让来访用户可以花费更多时间停留在系统上&#xff0c;则表明该系统设计得比较专…

Mellanox的LAG全称是什么?网卡的创建机制如何?(Link Aggregation Group 链路聚合组)

背景 对于双端口的网卡&#xff0c;有时候有将链路聚合的需求。在Mellanox网卡上通过LAG提供。对于RoCE的报文在Mellanox上也可以通过LAG来完成报文收发&#xff0c;叫做RoCE over LAG。但是仅仅适用于双端口卡。 关键点 LAG&#xff1a; Link Aggregation Group (LAG) 链路…

Spring Boot 与@Bean注解搭配场景

在Spring Boot中&#xff0c;Bean注解通常与其他注解一起使用&#xff0c;以实现更灵活的Bean管理、依赖注入和配置。以下是一些常见的搭配使用场景&#xff1a; 1. Bean与Configuration Bean注解通常用于配置类&#xff08;带有Configuration注解的类&#xff09;中&#xf…

APP自动化实战

APP自动化能做什么&#xff1f; 请看示例&#xff08;实现批量的视频&#xff0c;封面功能复用能力&#xff08;实现效果参考抖音号&#xff1a;71403700901&#xff09; APP自动化实战&#xff0d;操作剪映APP PO模式 1. PO模式介绍 PO&#xff08;Page Object&#xff09;…

Flutter 介绍及安装使用

Flutter 安装 1. 镜像的配置 Flutter 源站在国内可能不太稳定&#xff0c;因此谷歌中国开发者社区(GDG)专门搭建了临时镜像&#xff0c;使得我们的 Flutter 命令行工具可以到该镜像站点下载所需资源。 使用方法 Flutter SDK 默认从 Github 获取更新&#xff0c;如您访问 Github…