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

news/2025/2/27 7:14:10

文章目录

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

1、策略模式

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

public interface ClusterMetaDataProcessor {

    void processData();
 
}
public class Version4ClusterMetaDataProcessor implements ClusterMetaDataProcessor {

	@Override
	void processData() {
		//...
	}
}
public class Version5ClusterMetaDataProcessor implements ClusterMetaDataProcessor {

	@Override
	void 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;
    }

    @Override
    public 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 {
    
    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        // 此时可以立即使用 context 获取其他 Bean
        MyService service = context.getBean(MyService.class);
    }
}

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


http://www.niftyadmin.cn/n/5869697.html

相关文章

DeepSeek-R1的一些影响

DeepSeek-R1火爆全球&#xff0c;肯定不仅仅是开源了一篇论文、一个模型那么简单&#xff0c;更多的是其带来的一些影响&#xff0c;这里简单聊聊。 跳出大模型固有开发范式 NLP&大模型技术发展历程大致如下&#xff1a; 规则方法统计学习方法深度学习方法深度学习预训练…

智慧城市招标进入“资质严审期”!谁主数字孪生技术话语权?

2025年1月&#xff0c;《全国统一大市场建设指引》明确要求招标项目需杜绝“逐利性执法”&#xff0c;技术资质审查更趋透明化。与此同时&#xff0c;住建部《危险性较大的分部分项工程专项施工方案严重缺陷清单》将数字孪生平台的数据治理能力纳入工程验收标准。在此背景下&am…

记录Liunx安装Jenkins时的Package ‘jenkins‘ has no installation candidate

1、确保是否安装了Java&#xff0c;如果没有&#xff0c;可通过以下命令进行安装&#xff1a; sudo apt update sudo apt install openjdk-21-jre2、安装Jenkins sudo apt update sudo apt install jenkins执行sudo apt install jenkins时&#xff0c;可能会出现 意思是&…

C语言-6.数据类型

目录 6.1数据类型6.1.1数据类型:C语言有哪些是基础数据类型,sizeof可以做什么6.1.2数据类型:除了int,还有多少整数类型6.1.3整数的内部表达式:整数是如何表达的,尤其是负数如何表达的6.1.4整数的范围:如何推断整数类型所能表达的范围,越界了会咋样6.1.5整数的格式化:如…

flask 是如何分发请求的?

这篇博客会涉及一些 WSGI 的知识&#xff0c;不了解的可以看这篇博客&#xff0c;简单了解一下。 Python 的 WSGI 简单入门 一、请求在 flask 中的处理过程 我们先来看一下 werkzeug.routing 包下 Map 和 Rule 方法的使用&#xff0c;这里给出一个官方的示例&#xff08;我进…

构建逻辑思维链(CoT)为金融AI消除幻觉(保险理赔篇)

在上一篇文章中&#xff0c;我们介绍了如何利用亚马逊云科技的Amazon Bedrock GuardRails自动推理检查为金融行业的AI应用提升准确性&#xff0c;消除幻觉。在本案例中&#xff0c;我们将探讨一个利用AI副主保险公司评估长期护理保险理赔审核的场景。 自动推理检查配置 在本方…

Zama fhEVM应用:摩根大通旗下 Kinexys 发布概念验证

1. 引言 Zama 全同态加密 (FHE) 技术在摩根大通的 Kinexys&#xff08;以前称为 Onyx&#xff09;中成功进行了概念验证。该概念验证是“EPIC 项目&#xff1a;通过链上企业隐私、身份和可组合性推动代币化金融”的一部分&#xff0c;在 Kinexys 数字资产沙盒&#xff08;以前…

性能测试丨JMeter 分布式加压机制

JMeter 的分布式加压机制允许在多台机器上同时运行测试&#xff0c;以模拟更高的负载。以下是其工作原理和配置步骤&#xff1a; 1. 分布式架构 主节点&#xff08;Controller&#xff09;&#xff1a;负责管理测试计划、分发任务和收集结果。从节点&#xff08;Slave&#x…