SpringBoot applicationContext.getBeansOfType获取某一接口所有实现类,应用于策略模式

本文介绍了如何在Springboot项目中通过ApplicationContext获取接口的实现类,并通过枚举策略模式避免if/else,展示了如何使用`getBeansOfType`获取`TrafficModeService`的实现,以及如何在实际场景中应用,如查询交通方式费用

1 在实际工作中,我们经常会遇到一个接口及多个实现类的情况,并且在不同的条件下会使用不同的实现类。

应用场景

springboot 项目中通过 ApplicationContext.getBeansOfType(class) 获取某一接口的所有实现类,并通过枚举完成策略模式,替代 if/else,使代码更加优雅易于拓展。

三、ApplicationContext.getBeansOfType(class) 介绍

<T> Map<String, T> getBeansOfType(@Nullable Class<T> var1) throws BeansException;

从上面的源码上我们可以看出来这个方法能返回一个接口的全部实现类(前提是所有实现类都必须由 Spring IoC 容器管理)

复制代码
        Map<String, TrafficModeService> map = applicationContext.getBeansOfType(TrafficModeService.class);

从上面的代码上(下面案例中工厂类有) ,Map 中的 String 的值是各个实现类的名称 busModeServiceImpl、trainModeServiceImpl(首字母小写),Map 中的 value 是各个 key 对应的策略实现类

案例 demo

复制代码
1、TrafficCodeEmun 枚举制定接口信息

@AllArgsConstructor
public enum TrafficCodeEmun {
 
    TRAIN("TRAIN","火车"),
    BUS("BUS","大巴"),
 
    ;
 
    private final String code;
    private final String desc;
}


2、TrafficModeFactory 工厂类获取接口实现 bean,并存储到 ConcurrentHashMap,通过枚举获取对应的实现 bean

@Component
@Slf4j
public class TrafficModeFactory implements ApplicationContextAware {
 
    public static final ConcurrentHashMap<TrafficCodeEmun, TrafficModeService> TRAFFIC_BEAN_MAP = new ConcurrentHashMap<>();
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("TrafficModeFactory 启动开始");
        Map<String, TrafficModeService> map = applicationContext.getBeansOfType(TrafficModeService.class);
 
        map.forEach((key, value) -> TRAFFIC_BEAN_MAP.put(value.getCode(), value));
        log.info("TrafficModeFactory 启动完成");
    }
 
    public static <T extends TrafficModeService> T getTrafficMode(TrafficCodeEmun code) {
        return (T) TRAFFIC_BEAN_MAP.get(code);
      }
 
}


3、定义策略接口 TrafficModeService

public interface TrafficModeService {
 
    /**
     * 查询交通方式编码
     * @return 编码
     */
    TrafficCodeEmun getCode();
     
 
    /**
     * 查询交通方式的费用,单位:分
     * @return 费用
     */
    Integer getFee();
 
}


4、策略实现类 BusModeServiceImpl、TrainModeServiceImpl

@Service
public class TrainModeServiceImpl implements TrafficModeService {
 
    /**
     * 查询交通方式编码
     * @return 编码
     */
    @Override
    public TrafficCodeEmun getCode() {
        return TrafficCodeEmun.TRAIN;
    }
 
    /**
     * 查询交通方式的费用,单位:分
     * @return 费用
     */
    @Override
    public Integer getFee() {
        return 5000;
    }
 
}


5、定义 controller

    @PostMapping("/test3")
    public Integer test3() {
        Integer fee = TrafficModeFactory.getTrafficMode(TrafficCodeEmun.TRAIN).getFee();
        return fee;
    }


注意点:
一个策略接口被多个策略实现类所实现,具体使用哪一种根据用户选择的类型来和 Map 里的 key 做匹配,获取对应的实现来调用具体的策略方法。
使用 ConcurrentHashMap ,而不使用 HashMap ,是 put 的时候,键和值都不能为空,防止 key 对应的实现类没有注入进去,导致空指针的问题。
相关推荐
RuoyiOffice11 分钟前
Spring AI+Vue3 企业知识库设计:让每个答案有依据,让每份资料守住权限
java·spring boot·vue3·rag·企业知识库·spring ai·ruoyi office
倔强的石头1061 小时前
【Linux指南】进程通信系列(二):匿名管道 —— pipe 的本质、fork 继承与四种读写规则
java·linux·运维
调试优选官1 小时前
2026年IoT物联网开发赛道年度榜单深度解析:D-coding物联网系统定制与源码交付能力专项解读
java·物联网·struts·iot·开发经验
木井巳1 小时前
【动态规划】三步问题
java·算法·leetcode·动态规划·推荐算法
小张成长计划..1 小时前
【Linux】25:线程概念和控制
java·linux·jvm
智慧城市20301 小时前
关键供应商连续交付不合格批次,说明质量风险可能持续存在。企业需要建立“批次隔离、加严检验、驻厂遏制、复检放行、供应商升级”的处置闭环,同时统筹保供。
数据分析·策略模式·战略咨询·流程管理
蛋蛋的就会顺顺的10 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
需要82611 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
小 黄 鸡11 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
凤山老林12 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python