冰河技术
导读
♻学习路线
  • 面试必问系列

    • 面试必问
  • 架构与模式

    • Java极简设计模式
    • 实战高并发设计模式
  • Java核心技术

    • Java8新特性
    • IOC核心技术
    • JVM调优技术
  • 容器化核心技术

    • Dockek核心技术
  • 分布式存储

    • Mycat核心技术
  • 数据库核心技术

    • MySQL基础篇
  • 服务器核心技术

    • Nginx核心技术
  • 渗透核心技术

    • 渗透实战技术
  • 底层技术
  • 源码分析
  • 基础案例
  • 实战案例
  • 面试
  • 系统架构
  • Spring6核心技术
  • 分布式事务

    • 分布式事务系列视频
  • SpringBoot
  • SpringCloudAlibaba
  • 🔥AI大模型项目

    • 一站式AI智能平台
    • AI智能客服系统
    • AI智能问答系统
    • 实战AI大模型
  • 中间件项目

    • 手写高性能Redis组件
    • 手写高性能脱敏组件
    • 手写线程池项目
    • 手写高性能SQL引擎
    • 手写高性能Polaris网关
    • 手写高性能RPC项目
  • 高并发项目

    • 分布式IM即时通讯系统(新)
    • 分布式Seckill秒杀系统
    • 实战高并发设计模式
  • 微服务项目

    • 简易电商脚手架项目
  • 手撕源码

    • 手撕Spring6源码
🌍知识星球
  • 总览

    • 《书籍汇总》
  • 出版图书

    • 《深入理解高并发编程:核心原理与案例实战》
    • 《深入理解高并发编程:JDK核心技术》
    • 《深入高平行開發:深度原理&專案實戰》
    • 《深入理解分布式事务:原理与实战》
    • 《MySQL技术大全:开发、优化与运维实战》
    • 《海量数据处理与大数据技术实战》
  • 电子书籍

    • 《实战高并发设计模式》
    • 《深入理解高并发编程(第2版)》
    • 《深入理解高并发编程(第1版)》
    • 《从零开始手写RPC框架(基础篇)》
    • 《SpringCloud Alibaba实战》
    • 《冰河的渗透实战笔记》
    • 《MySQL核心知识手册》
    • 《Spring IOC核心技术》
  • 关于自己
  • 关于学习
  • 关于职场
B站
Github
导读
♻学习路线
  • 面试必问系列

    • 面试必问
  • 架构与模式

    • Java极简设计模式
    • 实战高并发设计模式
  • Java核心技术

    • Java8新特性
    • IOC核心技术
    • JVM调优技术
  • 容器化核心技术

    • Dockek核心技术
  • 分布式存储

    • Mycat核心技术
  • 数据库核心技术

    • MySQL基础篇
  • 服务器核心技术

    • Nginx核心技术
  • 渗透核心技术

    • 渗透实战技术
  • 底层技术
  • 源码分析
  • 基础案例
  • 实战案例
  • 面试
  • 系统架构
  • Spring6核心技术
  • 分布式事务

    • 分布式事务系列视频
  • SpringBoot
  • SpringCloudAlibaba
  • 🔥AI大模型项目

    • 一站式AI智能平台
    • AI智能客服系统
    • AI智能问答系统
    • 实战AI大模型
  • 中间件项目

    • 手写高性能Redis组件
    • 手写高性能脱敏组件
    • 手写线程池项目
    • 手写高性能SQL引擎
    • 手写高性能Polaris网关
    • 手写高性能RPC项目
  • 高并发项目

    • 分布式IM即时通讯系统(新)
    • 分布式Seckill秒杀系统
    • 实战高并发设计模式
  • 微服务项目

    • 简易电商脚手架项目
  • 手撕源码

    • 手撕Spring6源码
🌍知识星球
  • 总览

    • 《书籍汇总》
  • 出版图书

    • 《深入理解高并发编程:核心原理与案例实战》
    • 《深入理解高并发编程:JDK核心技术》
    • 《深入高平行開發:深度原理&專案實戰》
    • 《深入理解分布式事务:原理与实战》
    • 《MySQL技术大全:开发、优化与运维实战》
    • 《海量数据处理与大数据技术实战》
  • 电子书籍

    • 《实战高并发设计模式》
    • 《深入理解高并发编程(第2版)》
    • 《深入理解高并发编程(第1版)》
    • 《从零开始手写RPC框架(基础篇)》
    • 《SpringCloud Alibaba实战》
    • 《冰河的渗透实战笔记》
    • 《MySQL核心知识手册》
    • 《Spring IOC核心技术》
  • 关于自己
  • 关于学习
  • 关于职场
B站
Github
  • 专栏介绍

    • 第00章:开篇:我要带你一步步调试Spring6.0源码啦!
  • 第一篇:IOC容器

    • 第01章:深度解析@Configuration注解
    • 第02章:深度解析@ComponentScan注解
    • 第03章:深度解析@Bean注解
    • 第04章:深度解析从IOC容器中获取Bean的过程
    • 第05章:深度解析@Import注解
    • 第06章:深度解析@PropertySource注解
    • 第07章:深度解析@DependsOn注解
    • 第08章:深度解析@Conditional注解
    • 第09章:深度解析@Lazy注解
    • 【付费】 第10章:深度解析@Component注解(含@Repository、@Service和@Controller)
    • 【付费】 第11章:深度解析@Value注解
    • 【付费】 第12章:深度解析@Autowired注解
    • 【付费】 第13章:深度解析@Qualifier注解
    • 【付费】 第14章:深度解析@Resource注解
    • 【付费】 第15章:深度解析@Inject注解
    • 【付费】 第16章:深度解析@Primary注解
    • 【付费】 第17章:深度解析@Scope注解
    • 【付费】 第18章:深度解析@PostConstruct注解与@PreDestroy注解
    • 【付费】 第19章:深度解析@Profile注解
    • 【付费】第20章:深度解析循环依赖(史上最全)
    • 【付费】第21章:深度解析事件监听机制
  • 第二篇:AOP切面

    • 【付费】第22章:AOP切面型注解实战
    • 【付费】第23章:深度解析@EnableAspectJAutoProxy注解
    • 【付费】第24章:深度解析切入点表达式
    • 【付费】第25章:深度解析构建AOP拦截器链的流程
    • 【付费】第26章:深度解析调用通知方法的流程
    • 【付费】第27章:深度解析@DeclareParents注解
    • 【付费】第28章:@EnableLoadTimeWeaving注解
  • 第三篇:声明式事务

    • 【付费】第29章:Spring事务概述与编程实战
    • 【付费】第30章:深度解析Spring事务三大接口
    • 【付费】第31章:深度解析Spring事务隔离级别与传播机制
    • 【付费】第32章:深度解析@EnableTransactionManagement注解
    • 【付费】第33章:深度解析@Transactional注解
    • 【付费】第34章:深度解析Spring事务的执行流程
    • 【付费】第35章:深度解析Spring底层事务传播机制源码
    • 【付费】第36章:深度解析@TransactionEventListener注解
    • 【付费】第37章:七大场景深度分析Spring事务嵌套最佳实践
    • 【付费】第38章:深度解析Spring事务失效的八大场景
  • 第四篇:AOT预编译

    • 第39章:AOT预编译技术概述
    • 【付费】第40章:手动构建Native Image
    • 【付费】第41章:Maven构建Native Image
  • 第五篇:SpringMVC

    • 【付费】第42章:注解型SpringMVC通用SpringBoot启动模型设计与实现
    • 【付费】第43章:深度解析@Controller注解
    • 【付费】第44章:深度解析@RestController注解
    • 【付费】第45章:深度解析@RequestMapping注解
    • 【付费】第46章:深度解析@RequestParam注解
    • 【付费】第47章:深度解析@PathVariable注解
    • 【付费】第48章:深度解析@RequestBody注解
    • 【付费】第49章:深度解析@RequestHeader注解
    • 【付费】第50章:深度解析@CookieValue注解
    • 【付费】第51章:深度解析@ModelAttribute注解
    • 【付费】第52章:深度解析@ExceptionHandler注解
    • 【付费】第53章:深度解析@InitBinder注解
    • 【付费】第54章:深度解析@ControllerAdvice注解
    • 【付费】第55章:深度解析@RequestAttribute注解
    • 【付费】第56章:深度解析@SessionAttribute注解
    • 【付费】第57章:深度解析@SessionAttributes注解
    • 【付费】第58章:深度解析@ResponseBody注解
    • 【付费】第59章:深度解析@CrossOrigin注解
  • 作业篇

    • 作业:专栏整体作业

《Spring核心技术》第21章:深度解析事件监听机制

作者:冰河
星球:http://m6z.cn/6aeFbs
博客:https://binghe.site
文章汇总:https://binghe.site/md/all/all.html
源码地址:https://github.com/binghe001/spring-annotation-book/tree/master/spring-annotation-chapter-21

沉淀,成长,突破,帮助他人,成就自我。

大家好,我是冰河~~


  • 本章难度:★★★★☆

  • 本章重点:进一步学习并掌握Spring事件监听机制的案例和流程,从源码级别彻底掌握Spring事件监听机制的底层执行流程。


本章目录如下所示:

  • 学习指引
  • 事件监听机制
    • 事件原理
    • Spring内置事件
    • 自定义事件
  • 使用案例
    • 同步事件监听机制案例
    • 异步事件监听机制案例
  • 源码时序图
    • 基于接口实现
    • 基于注解实现
  • 源码解析
    • 基础接口实现
    • 基于注解实现
  • 总结
  • 思考
  • VIP服务

一、学习指引

Spring中的事件监听机制,你真的彻底了解过吗?

Spring中提供了事件监听机制,能够非常方便的发布和接收事件,并且Spring中的事件监听机制使用了观察者模式,这些你都了解过吗?

二、事件监听机制

简单聊聊事件监听机制吧?

本章,从Spring内置事件、自定义事件和事件原理两个方面简单聊聊Spring中的事件监听机制。

2.1 事件原理

Spring中的事件监听总体上可以分成:事件、事件监听器和事件广播器。

图21-1

其中,每个部分的主要说明如下所示。

  • 事件:对应事件的监听器,事件源发生了某种事件后,会被对应的事件监听器感知到。
  • 事件监听器:监听某种特定的事件,并且会对监听到的事件做对应的逻辑处理。对应观察者模式中的观察者。
  • 事件广播器:对外提供维护事件监听器,比如新增事件监听器和删除事件监听器的接口,并且支持对外发布事件,维护事件监听器和事件之间的对应关系。也能够在发生事件时,通知对应的事件监听器。

在Spring的事件监听机制中,事件广播器和事件监听器之间还有一个EventMultiCaster角色负责把事件转发给事件监听器,如图21-2所示。

图21-2

EventMultiCaster上注册着所有的事件监听器,事件广播器会将事件发送给EventMultiCaster,然后由EventMultiCaster将事件转发给事件监听器。

2.2 Spring内置事件

在Spring中,事件类需要继承ApplicationEvent类,Spring中的内置事件则会继承ApplicationContextEvent类。如图21-3所示。

图21-3

Spring中的内置事件由Spring内部进行发布,不需要注入监听器,例如Spring中提供了如下事件类,都是Spring的内置事件。

  • ContextRefreshedEvent:当IOC容器被实例化或者refresh()时会发布ContextRefreshedEvent事件,此时Bean都已经被IOC容器加载,后置处理器也已经被激活,所有的单例Bean都已经被实例化。
  • ContextStartedEvent:当IOC容器启动,即调用start()方法时,会发布ContextStartedEvent事件,此时,所有处于生命周期内的Bean都接收到了start信号。
  • ContextStoppedEvent:当IOC容器停止,即调用stop()方法时,会发布ContextStoppedEvent事件,此时,所有处于生命周期内的Bean都接收到了stop信号。调用stop()方法关闭的IOC容器,可以调用start()方法重启。
  • ContextClosedEvent:当IOC容关闭,即调用close()方法时,会发布ContextClosedEvent事件,此时IOC容器中所有的单例Bean都已经被销毁。调用close()方法关闭的IOC容器,不能调用start()方法重启,也不能调用refresh()方法刷新IOC容器。

2.3 自定义事件

Spring允许基于ApplicationEvent类自定义监听的事件,如果在实际项目开发的过程中,需要使用自定义事件监听机制,则可以继承ApplicationEvent类实现要监听的事件,例如,如下代码所示。

public class ListenerEvent extends ApplicationEvent {
    private String name;
    public ListenerEvent(Object source, String name) {
        super(source);
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

三、使用案例

一起实现事件监听的案例,怎么样?

本章,主要从同步和异步两个方面实现Spring的事件监听机制案例。

3.1 同步事件监听机制案例

本节,就简单实现一个Spring基于同步事件监听机制实现的案例程序,具体实现步骤如下所示。

(1)新增ListenerEvent类

ListenerEvent类的源码详见:spring-annotation-chapter-21工程下的io.binghe.spring.annotation.chapter21.event.ListenerEvent。

public class ListenerEvent extends ApplicationEvent {
    public static final String EVENT_SYNC = "sync";
    public static final String EVENT_ASYNC = "async";
    private String name;
    public ListenerEvent(Object source, String name) {
        super(source);
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

可以看到,ListenerEvent类继承了ApplicationEvent类,说明ListenerEvent类是一个自定义的事件类。在ListenerEvent类中定义了两个常量,一个是EVENT_SYNC表示同步事件监听机制,一个是EVENT_ASYNC异步事件监听机制。

不管是实现同步事件监听机制的案例,还是实现异步事件监听机制的案例,都会使用ListenerEvent这个自定义事件类。

(2)新增SyncEventListener类

SyncEventListener类的源码详见:spring-annotation-chapter-21工程下的io.binghe.spring.annotation.chapter21.sync.listener.SyncEventListener。

@Component
public class SyncEventListener implements ApplicationListener<ListenerEvent> {
    @Override
    public void onApplicationEvent(ListenerEvent event) {
        if (ListenerEvent.EVENT_SYNC.equals(event.getName())){
            System.out.println("同步事件监听器...");
        }
    }
}

可以看到,SyncEventListener类实现了ApplicationListener接口,表示SyncEventListener类是一个事件监听器类,重写了ApplicationListener接口的onApplicationEvent()方法,用于监听同步事件。

在Spring中除了实现ApplicationListener接口来实现事件监听器外,也可以使用@EventListener注解实现事件监听,如下所示。

@Component
public class SyncAnnotationEventListener {
    @EventListener(ListenerEvent.class)
    public void onApplicationEvent(ListenerEvent event){
        if (ListenerEvent.EVENT_SYNC.equals(event.getName())){
            System.out.println("同步事件监听器...");
        }
    }
}

(3)新增SyncEventListenerConfig类

SyncEventListenerConfig类的源码详见:spring-annotation-chapter-21工程下的io.binghe.spring.annotation.chapter21.sync.config.SyncEventListenerConfig。

@Configuration
@ComponentScan(value = {"io.binghe.spring.annotation.chapter21.sync"})
public class SyncEventListenerConfig {
}

可以看到,在SyncEventListenerConfig类上标注了@Configuration注解,说明SyncEventListenerConfig类是案例程序的配置类,并使用@ComponentScan注解指定了要扫描的包名。

(4)新增SyncEventListenerTest类

SyncEventListenerTest类的源码详见:spring-annotation-chapter-21工程下的io.binghe.spring.annotation.chapter21.sync.SyncEventListenerTest。

public class SyncEventListenerTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SyncEventListenerConfig.class);
        context.publishEvent(new ListenerEvent(new SyncEventListenerTest(), ListenerEvent.EVENT_SYNC));
        context.close();
    }
}

可以看到,在SyncEventListenerTest类的main()方法中,通过context的publishEvent()方法发布事件。

(5)运行SyncEventListenerTest类

运行SyncEventListenerTest类的main()方法,输出的结果信息如下所示。

同步事件监听器...

可以看到,正确输出了SyncAnnotationEventListener类中打印的日志信息。

3.2 异步事件监听机制案例

本节,就简单实现一个Spring基于异步事件监听机制实现的案例程序,具体实现步骤如下所示。

(1)新增AsyncEventListener类

AsyncEventListener类的源码详见:spring-annotation-chapter-21工程下的io.binghe.spring.annotation.chapter21.async.listener.AsyncEventListener。

@Component
public class AsyncEventListener implements ApplicationListener<ListenerEvent> {
    @Override
    public void onApplicationEvent(ListenerEvent event) {
        if (ListenerEvent.EVENT_ASYNC.equals(event.getName())){
            System.out.println("异步事件监听器...");
        }
    }
}

可以看到,AsyncEventListener类与SyncEventListener类的实现基本相同,只是AsyncEventListener类会监听异步实现。除了可以实现ApplicationListener接口外,异步事件监听机制也可以基于@EventListener注解实现,如下所示。

@Component
public class AsyncAnnotationEventListener {
    @EventListener(ListenerEvent.class)
    public void onApplicationEvent(ListenerEvent event) {
        if (ListenerEvent.EVENT_ASYNC.equals(event.getName())){
            System.out.println("异步事件监听器...");
        }
    }
}

(2)新增ThreadPoolConfig类

ThreadPoolConfig类的源码详见:spring-annotation-chapter-21工程下的io.binghe.spring.annotation.chapter21.async.config.ThreadPoolConfig。

@Configuration
public class ThreadPoolConfig {
    @Bean("bingheExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //设置线程池参数信息
        taskExecutor.setCorePoolSize(8);
        taskExecutor.setMaxPoolSize(20);
        taskExecutor.setQueueCapacity(50);
        taskExecutor.setKeepAliveSeconds(60);
        taskExecutor.setThreadNamePrefix("binghe-executor--");
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住。
        taskExecutor.setAwaitTerminationSeconds(60);
        //修改拒绝策略为使用当前线程执行
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //初始化线程池
        taskExecutor.initialize();
        return taskExecutor;
    }
}

可以看到,在ThreadPoolConfig类中主要实现了一个线程池。

(3)新增AsyncEventListenerConfig类

AsyncEventListenerConfig类的源码详见:spring-annotation-chapter-21工程下的io.binghe.spring.annotation.chapter21.async.config.AsyncEventListenerConfig。

@Configuration
@ComponentScan(value = {"io.binghe.spring.annotation.chapter21.async"})
public class AsyncEventListenerConfig {
    @Autowired
    @Qualifier("bingheExecutor")
    private Executor taskExecutor;

    @Bean(name = AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)
    public ApplicationEventMulticaster applicationEventMulticaster(){
        SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
        simpleApplicationEventMulticaster.setTaskExecutor(taskExecutor);
        return simpleApplicationEventMulticaster;
    }
}

可以看到,在AsyncEventListenerConfig类中注入了线程池taskExecutor,并向IOC容器中重新注入了ApplicationEventMulticaster类型的Bean对象,通过setTaskExecutor()方法向ApplicationEventMulticaster类型的Bean对象中设置了线程池对象。

(4)新增AsyncEventListenerTest类

AsyncEventListenerTest类的源码详见:spring-annotation-chapter-21工程下的io.binghe.spring.annotation.chapter21.async.AsyncEventListenerTest。

public class AsyncEventListenerTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AsyncEventListenerConfig.class);
        context.publishEvent(new ListenerEvent(new AsyncEventListenerTest(), ListenerEvent.EVENT_ASYNC));
        context.close();
    }
}

可以看到,在AsyncEventListenerTest类中,也会调用context的publishEvent()发布异步事件。

(5)运行AsyncEventListenerTest类

运行AsyncEventListenerTest类的main()方法,输出的结果信息如下所示。

异步事件监听器...

可以看到,结果信息中打印了在AsyncAnnotationEventListener类中输出的结果信息。

查看完整文章

加入冰河技术知识星球,解锁完整技术文章与完整代码

在 GitHub 上编辑此页
上次更新: 2026/4/29 16:18
Contributors: binghe001
Prev
【付费】第20章:深度解析循环依赖(史上最全)
阅读全文
×

扫码或搜索:冰河技术
发送:290992
即可立即永久解锁本站全部文章

星球会员
跳转链接