spring学习笔记(16)趣谈spring 事件机制[2]:多监听器流水线式顺序处理

上一篇我们使用到的ApplicationListener是无序的,结合异步调度它能满足了我们的大部分应用场景,但现在我们来个另类的需求,我们来模拟一条作业调度流水线,它不能异步,必须按照先后次序执行不同的任务才能得到我们的最终结果。
需求示例:现在假如华中科技大学的小白想要为它的智能机器人作品申报国家创新奖,需要经过学校、省级创新科研机构、国家创新科研机构逐层审核。我们尝试通过事件来实现,核心就在监听器实现SmartApplicationListener接口。示例如下:

1. 配置事件发布者小白:

public class XiaoBai implements ApplicationContextAware {

    private ApplicationContext applicationContext;//底层事件发布者

    public void reportWorks(){//申报作品
        AuditEvent auditEvent = new AuditEvent(this);
        applicationContext.publishEvent(auditEvent);
        //小白获取期待已久的最终结果
        System.out.println("最终审核结果:" + auditEvent.getStatus() + "——" + auditEvent.getAdvice());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }
}

关于上述配置可参考我的上一篇文章《spring学习笔记(13)趣谈spring 事件:实现业务逻辑解耦,异步调用提升用户体验》

2. 配置审核事件源

public class AuditEvent extends ApplicationEvent {

    private Boolean status ; //当前申报状态
    private String work;//申报作品
    private String advice;//当前申报意见


    public AuditEvent(Object  source) {
        super(source);
        status = true;//初始窗台
        advice = "尚未审核";
    }
    //ignore getter and setter 
}

3. 配置事件监听器

我们实现需求的核心部分来了,先上代码

/******************学校审核监听器******************/
public class SchoolListener implements SmartApplicationListener {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("获取当前的申报状态为:"+((AuditEvent)event).getStatus() + "——" + ((AuditEvent)event).getAdvice());
        ((AuditEvent)event).setStatus(true);
        ((AuditEvent)event).setAdvice("学校审核意见:有创意,非常棒!");
    }

    @Override
    public int getOrder() {
        return 1;//获取学校监听(审核)的优先级
    }

    @Override//这是我们的监听器智能所在之一,能够根据事件类型动态监听
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return eventType == AuditEvent.class;
    }

    @Override//这是我们的监听器智能所在之二,能够根据事件发布者类型动态监听
    public boolean supportsSourceType(Class<?> sourceType) {
        return sourceType == XiaoBai.class;
    }
}
/******************省级审核监听器******************/
public class ProvinceListener implements SmartApplicationListener {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if(((AuditEvent)event).getStatus()){//如果上层审核通过
            System.out.println("获取当前的申报状态为:"+((AuditEvent)event).getStatus() + "——" + ((AuditEvent)event).getAdvice());
            ((AuditEvent)event).setStatus(true);
            ((AuditEvent)event).setAdvice("省级审核意见:还行,通过吧!");
        }
    }

    @Override
    public int getOrder() {
        return 2;
    }

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return eventType == AuditEvent.class;
    }

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return sourceType == XiaoBai.class;
    }

}

/******************国家级审核监听器******************/
public class CountryListener implements SmartApplicationListener {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if(((AuditEvent)event).getStatus()){//如果上层审核通过
            System.out.println("获取当前的申报状态为:"+((AuditEvent)event).getStatus() + "——" + ((AuditEvent)event).getAdvice());
            ((AuditEvent)event).setStatus(true);
            ((AuditEvent)event).setAdvice("国家审核意见:一般般,勉强通过吧!");
        }
    }

    @Override
    public int getOrder() {
        return 3;
    }

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return eventType == AuditEvent.class;
    }

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return sourceType == XiaoBai.class;
    }

}

在这里,我们的实例为了方便演示而简化配置。我们的发布源支持类型是小白,根据更实际的需求,我们可以让小白继承Student类,然后让sourceType只要是Student的子类即可,这样就能满足任何继承了Student的学生都能申报了。
在实现了SmartApplicationListener的监听器中,我们通过重写GetOrder方法来修改不同监听器的顺序,优先级越小,则越先被调用。通过配置不同的优先级,且让监听器之间阻塞调用。我们就能实现流水线式的有序事件调用,这在实际应用场景中还是蛮有意义的

5. 在IOC容器中注册监听器

<bean id="schoolListener" class="test.event2.SchoolListener" />
<bean id="provinceListener" class="test.event2.ProvinceListener" />
<bean id="countryListener" class="test.event2.CountryListener" />

<bean id="xiaoBai" class="test.event2.XiaoBai" /><!-- 测试时注入使用 -->

6. 测试方法

public class MainTest {
    public static void main(String args[]) throws InterruptedException{
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:test/event2/event.xml");
        XiaoBai xiaobai = (XiaoBai) ac.getBean("xiaoBai");
        xiaobai.reportWorks();//小白要开始申报项目啦
    }
}

调用测试代码,我们得到运行结果:
获取当前的申报状态为:true——尚未审核
获取当前的申报状态为:true——学校审核意见:有创意,非常棒!
获取当前的申报状态为:true——省级审核意见:还行,通过吧!
最终审核结果:true——国家审核意见:一般般,勉强通过吧!

于是,小白的作品终于评上了国家创新科技奖了,这让他高兴了好一阵子。

源码下载

本实例源码可到我的github仓库https://github.com/jeanhao/spring下的event2文件夹下载

你可能感兴趣的:(spring,事件机制,顺序监听器,多监听器配置)