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

简介: <div class="markdown_views"><p>上一篇我们使用到的ApplicationListener是无序的,结合异步调度它能满足了我们的大部分应用场景,但现在我们来个另类的需求,我们来模拟一条<strong>作业调度流水线</strong>,它不能异步,必须按照先后次序执行不同的任务才能得到我们的最终结果。 <br>需求示例:现在假如华中科技大学的小白想

上一篇我们使用到的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文件夹下载

目录
相关文章
|
19天前
|
缓存 安全 Java
Spring高手之路26——全方位掌握事务监听器
本文深入探讨了Spring事务监听器的设计与实现,包括通过TransactionSynchronization接口和@TransactionalEventListener注解实现事务监听器的方法,并通过实例详细展示了如何在事务生命周期的不同阶段执行自定义逻辑,提供了实际应用场景中的最佳实践。
40 2
Spring高手之路26——全方位掌握事务监听器
|
16天前
|
缓存 Java 数据库连接
Spring框架中的事件机制:深入理解与实践
Spring框架是一个广泛使用的Java企业级应用框架,提供了依赖注入、面向切面编程(AOP)、事务管理、Web应用程序开发等一系列功能。在Spring框架中,事件机制是一种重要的通信方式,它允许不同组件之间进行松耦合的通信,提高了应用程序的可维护性和可扩展性。本文将深入探讨Spring框架中的事件机制,包括不同类型的事件、底层原理、应用实践以及优缺点。
46 8
|
1月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
63 9
|
2月前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
41 9
|
1月前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
32 0
|
2月前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
27 1
|
2月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
100 2
|
2月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
194 1
|
2月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
34 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
2月前
|
Java API Spring
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中过滤器的基础知识和实战项目应用的教程。
36 0
springboot学习六:Spring Boot2.x 过滤器基础入门&实战项目场景实现
下一篇
DataWorks