利用spring事件和监听机制实现容器启动时的构建某业务服务类容器(Map)

背景:基于trade项目的启发,当项目中某个功能,需要根据业务场景ABC,区分不同的Service类处理。比如,针对一个统一的消息接受类,根据消息的不同场景,分散到不同的executor执行器里去执行;或者是针对一个统一的对外开放接口(Controller层),根据不同的业务场景,分配对应的service处理。

思考:针对这个场景,可以拿到容器里所有对应处理类(executor或者Service)。可以存成一个map<name,Class>的map格式,然后在对饮需要分配的地方,基于面向接口的思想,分配不同的处理类进行处理。

实现方式:

根据目前项目中的使用,有两个使用方式(以针对不同场景有多个executor为例)

1. 一个实现ApplicationContextAware的注册器。

实现ApplicationContextAware接口的类会实现一个setApplicationContext方法,可以获得当前ApplicationContext容器本身。

因此项目中的多个Executor实现类都设计为实现ExecutorInterface接口,为根据名称获取方便,可以定义一个getName的方法指定对应实现Executor类对应的名字。每个Executor实现类都@Component交由spring托管。  专门编写一个ExecutorRegistry类实现ApplicationContextAware接口,用于注册所有的executor实现类。

@Component
@Slf4j
public class MessageExecutorRegistry implements ApplicationContextAware {

    private Map<String, MessageExecutor> messageExecutorMap;   //用于存储executor实现类和类名对应的map,前置方法从这个map里拿取对应的executor实现类


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, MessageExecutor> messageExecutorBeanMap = applicationContext.getBeansOfType(MessageExecutor.class);   //获取容器中所有messageExecutor实现类
        messageExecutorMap = Maps.newHashMap();
        messageExecutorBeanMap.forEach((beanName, executorBean) -> messageExecutorMap.put(executorBean.getBizCode(),executorBean));
        log.info("存入map的bean数量:" + messageExecutorMap.size());
    }

    public MessageExecutor getExecutorByCode(String bizCode){
        return messageExecutorMap.get(bizCode);
    }
}

基于以上代码,可以获得一个包含容器内所有执行器类的map,并对外提供一个getByCode的方法,在需要的地方调用getByCode方法,获取所需的执行器。

 

2.利用ApplicationListener<ContextRefreshedEvent>,即spring的消息监听机制

实现一个实现了ApplicationListener的类,监听ContextRefreshedEvent时间,这个事件是在spring容器所有bean加载完成后,刷新整个容器用的。实现ApplicationListener的类需要实现onApplicationEvent方法,这个方法就是在event出发的时候调用,可以用event.getApplicationContext方法获得最新的容器,接下来的步骤和方法1是类似的,通过applicationContext.getBeansOfType获得所有bean,并将其封装到map里,对外提供根据name或code获取map中value也就是bean类本身的方法。

public class ServiceContainer implements ApplicationListener<ContextRefreshedEvent> {

    private static Map<String, TrainBaseService> container = Maps.newHashMap();

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext applicationContext = event.getApplicationContext();

        Preconditions.checkNotNull(applicationContext, "applicationContext is null");

        //获取TrainBaseService类型接口类
        Map<String, TrainBaseService> serviceBeanMap = applicationContext.getBeansOfType(TrainBaseService.class);
        if (MapUtils.isEmpty(serviceBeanMap)) {
            return;
        }
        // 注册service bean到容器
        registerAllService(serviceBeanMap);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值