Spring事件监听机制使用和原理解析

这篇具有很好参考价值的文章主要介绍了Spring事件监听机制使用和原理解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

你好,我是刘牌!

前言

好久没有更新Spring了,今天来分享一下Spring的事件监听机制,之前分享过一篇Spring监听机制的使用,今天从原理上进行解析,Spring的监听机制基于观察者模式,就是就是我们所说的发布订阅模式,这种模式可以在一定程度上实现代码的解耦,如果想要实现系统层面的解耦,那么消息队列就是我们的不二选择,消息队列本身也是发布订阅模式,只是不同的消息队列的实现方式不一样。

使用

之前的文章我们使用了注解的方式,今天我们使用接口的方式来实现。

定义事件

如下定义了一个事件AppEvent,它继承了ApplicationEvent类,如果我们要使用Spring的事件监听机制,那么我们定义的事件必须继承ApplicationEvent ,否则就无法使用。

/**
 * 功能说明: 事件
 * <p>
 * Original @Author: steakliu-刘牌, 2023-03-30  11:02
 * <p>
 * Copyright (C)2020-2022  steakliu All rights reserved.
 */
public class AppEvent extends ApplicationEvent {
    private final String event;

    public AppEvent(Object source, String event) {
        super(source);
        this.event = event;
    }

    public String getEvent() {
        return event;
    }
}

定义事件监听器

事件监听器实现了ApplicationLister接口,其泛型为ApplicationEvent,因为要监听事件,所以必须按照Spring的规则来,onApplicationEvent方法就是监听到的事件,在这里我们可以进行我们的业务处理,我们可以看出AppLister我们加上了@Component注解,因为事件监听器需要加入Spring IOC容器中才能生效。

/**
 * 功能说明:事件监听器
 * <p>
 * Original @Author: steakliu-刘牌, 2023-03-30  11:03
 * <p>
 * Copyright (C)2020-2022  steakliu All rights reserved.
 */
@Component
public class AppListener implements ApplicationListener<AppEvent> {
    @Override
    public void onApplicationEvent(AppEvent event) {
        System.out.println("event:  "+event.getEvent());
    }
}

事件发布器

有了事件监听器,就需要发布事件,所以就需要一个事件发布器,事件发布器使用的是ApplicationEventPublisher,使用它的publishEvent方法进行事件发布。

/**
 * 功能说明:事件发布器
 * <p>
 * Original @Author: steakliu-刘牌, 2023-06-11  13:55
 * <p>
 * Copyright (C)2020-2022  steakliu All rights reserved.
 */
@Component
public class AppPublisher {

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    public void publish(){
        applicationEventPublisher.publishEvent(new AppEvent(new AppListener(),"publish event"));
    }
}

测试

为了方便,这里直接使用SpringBoot来进行测试,先获取AppPublisher,然后调用publish发布事件。

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        AppPublisher publisher = context.getBean(AppPublisher.class);
        publisher.publish();
    }
}

上面整个事件发布的代码就写完了,我们可以看出其实还是比较简单的,里面最核心的三个组件分别为,事件(Event)监听器(Listener)发布器(Publisher),实际使用中我们可以根据自己的需求去实现。

原理

上面我们知道了Spring的事件监听机制的基本使用,那么整个事件在Spring中是怎么流转的呢,我们很有必要去弄清楚。

我们使用的是SpringBoot项目来进行测试,我们先找到SpringBoot对事件监听机制进行处理的入口,然后再进行分析,SpringBoot对上下文进行处理的入口类是AbstractApplicationContext,它是Spring的入口,其中我们主要关注的refresh()方法,因为refresh中的方法比较多,我们下面只保留了三个方法。

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
    // Initialize event multicaster for this context.
				initApplicationEventMulticaster();
				// Check for listener beans and register them.
				registerListeners();
				// Last step: publish corresponding event.
				finishRefresh();
			}
		}
	}

initApplicationEventMulticaster()

ApplicationEventMulticaster是一个接口,它定义了如何将ApplicationEvent传递给事件监听者(event listener)。该接口有多个实现类,可以使用不同的策略将事件分派给不同的监听者。

ApplicationEventMulticaster为Spring事件机制的核心之一,它支持在应用中传递事件,并且可以将事件广播给多个监听者。在Spring中,事件是由ApplicationEvent及其子类表示的,例如ContextStartedEvent和ContextStoppedEvent等。当某些事件发生时,Spring容器将使用事件广播机制来通知感兴趣的监听者。

这个方法的作用是对ApplicationEventMulticaster进行赋值,Spring在初始化的时候会将ApplicationEventMulticaster注册进IOC容器,这里就只是单纯从IOC容器中获取ApplicationEventMulticaster来进行赋值,以方便后续的使用。

protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
            this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
            if (logger.isTraceEnabled()) {
                logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
            }
        } else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
            if (logger.isTraceEnabled()) {
                logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                        "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
            }
        }
    }

registerListeners()

这个方法的作用主要就是注册监听器,它会从IOC容器获取到我们注册的监听器,然后将其加入到Multicaster中,在AbstractApplicationEventMulticaster中,使用一个Set集合来装监听器。

public final Set<String> applicationListenerBeans = new LinkedHashSet<>();

finishRefresh()

finishRefresh()的作用是发布事件,里面是一些发布事件的逻辑,但是由于我们还没有正式发布事件,所以这里并不会发布事件,当我们使用applicationEventPublisher的publishEvent方法发布事件时,才会真正的发布事件。

ApplicationEventPublisher发布事件

上面示例中使用ApplicationEventPublisher的publishEvent发布事件,最终会进入AbstractApplicationContext类中进行事件发布,我们只关注最重要的方法multicastEvent(),它是广播器ApplicationEventMulticaster的一个方法事件都是由广播器进行发布。

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
  getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}

ApplicationEventMulticaster真正发布事件

ApplicationEventPublisher并没有真正发布事件,它相当于只是抽象了事件的发布,为了让我们更加简单和方便使用,但是真正发布事件的是ApplicationEventMulticaster,在multicastEvent()方法中,如果我们配置了线程池,那么事件就会被加入线程池,从而异步执行,如果没有设置线程池,那么就同步执行,最终执行都是调用invokeListener()方法。

public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        Executor executor = getTaskExecutor();
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            if (executor != null) {
                executor.execute(() -> invokeListener(listener, event));
            } else {
                invokeListener(listener, event);
            }
        }
    }

默认是不会使用线程池的,如果我们需要事件异步执行,那么可以配置线程池,其核心就是给广播器SimpleApplicationEventMulticaster的成员变量taskExecutor设置

/**
 * 功能说明: 事件任务线程池
 * <p>
 * Original @Author: steakliu-刘牌, 2023-06-11  13:17
 * <p>
 * Copyright (C)2020-2022  steakliu All rights reserved.
 */
@Configuration
public class TaskExecutor {

    @Bean("eventTaskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(10);
        threadPoolTaskExecutor.setMaxPoolSize(20);
        threadPoolTaskExecutor.setKeepAliveSeconds(10);
        threadPoolTaskExecutor.setThreadNamePrefix("application-event-thread");
        threadPoolTaskExecutor.setQueueCapacity(100);
        threadPoolTaskExecutor.setAllowCoreThreadTimeOut(true);
        threadPoolTaskExecutor.setAllowCoreThreadTimeOut(true);
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

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

}

invokeListener

invokeListener最终会通过传入的监听器去调用目标监听器,也就是我们自定义的监听器,主要代码如下,我们可以看到最终调用onApplicationEvent方法,就是我们上面示例AppListener监听器的onApplicationEvent方法。

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		 listener.onApplicationEvent(event);
}    

到这里,整个流程就完了,我们梳理一下重要的组件。

  • ApplicationEvent
  • ApplicationListener
  • ApplicationEventPublisher
  • ApplicationEventMulticaster

上面的四个组件基本上就是Spring事件监听机制的全部,ApplicationEvent是事件的规范,ApplicationListener是监听器,ApplicationEventPublisher是发布器,ApplicationEventMulticaster是广播器,其实ApplicationEventMulticaster和ApplicationEventPublisher本质是一样的,都能完成事件的发布,ApplicationEventPublisher最终也是去调用ApplicationEventMulticaster,只不过它只专注于事件发布,单独提出一个接口来,职责更加单一,这也是一种设计思想。

总结

上面对Spring事件监听机制的使用和原理进行了详细的介绍,并对其中涉及的组件进行解析,Spring事件监听机制是一个很不错的功能,我们在进行业务开发的时候可以引入,在相关的开源框架中也是用它的身影,比如高性能网关ShenYu中就使用了Spring事件监听机制来发布网关的更新数据,它可以降低系统的耦合性,使系统的扩展性更好。

今天的分享就到这里,感谢你的观看,我们下期见,如果文中有说得不合理或者不对的地方,希望你能指出,我们进行交流!文章来源地址https://www.toymoban.com/news/detail-479738.html

到了这里,关于Spring事件监听机制使用和原理解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ZooKeeper源码解析——学习ApacheZookeeper原理,掌握其核心组件的数据模型、监听通知机制等

    作者:禅与计算机程序设计艺术 随着互联网的飞速发展,各种信息数据越来越多,数据的存储也越来越依赖于分布式文件系统或NoSQL数据库。而传统的单机数据库往往不具备弹性可扩展性和高可用容错能力,在面对海量数据时难免会遇到性能瓶颈。为了解决这一问题,人们又

    2024年02月10日
    浏览(40)
  • 从注解@EventListener和@TransactionalEventListener掌握Spring的事件机制原理

    Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式;为的就是业务系统逻辑的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。 在Spring中我们可以通过实现

    2024年02月06日
    浏览(29)
  • 使用上 Spring 的事件机制

    本文主要是简单的讲述了Spring的事件机制,基本概念,讲述了事件机制的三要素事件、事件发布、事件监听器。如何实现一个事件机制,应用的场景,搭配@Async注解实现异步的操作等等。希望对大家有所帮助。 Spring的事件机制的基本概念 Spring的事件机制是Spring框架中的一个

    2024年02月14日
    浏览(37)
  • 【Android学习笔记】事件监听机制详解

    两种事件处理机制 基于监听的事件处理 基于回调的事件处理 涉及到的三类对象 Event Source事件源,指各个组件。 Event 界面组件上发生的特定的事情,。 Event Listener监听事件源发生的事情。并对各种事情作出相应的响应。 Event Handler事件处理器,当事件监听器捕获事件后,由响

    2024年02月11日
    浏览(58)
  • 45. Fabric2.2 事件监听机制应用

    本节全面讲述Fabric事件监听机制,并用实际客户端代码演示事件监听的特点、特性。 1. Fabric 2.2 支持的事件类型 RegisterBlockEvent : 区块事件监听,当产生区块时客户端收到消息,接收到完整的区块数据。 RegisterFilteredBlockEvent :也是区块事件监听,但完整的区块数据结构复杂,

    2023年04月26日
    浏览(37)
  • 【Spring | 事件监听详解】

    上篇 Spring 事件监听概述 对 Spring 事件监听的机制有了个基本的了解。 本篇来详细的解读下Spring 的 事件监听机制 。    ApplicationEvent 最重要的子类是 ApplicationContextEvent 抽象类, ApplicationContextEvent 是spring容器Context生命周期事件的基类。 ApplicationContextEvent 的有四个子类,如

    2024年02月12日
    浏览(36)
  • DAY4,Qt(事件处理机制的使用,Qt中实现服务器的原理)

    ---chatser.h---头文件 ---chatser.cpp---函数实现文件 ---main.cpp---测试文件 结果展示---     

    2024年02月15日
    浏览(57)
  • Spring boot 实现监听 Redis key 失效事件

    方式一:修改配置文件 redis.conf 方式二:命令行开启 notify-keyspace-events 选项的默认值为空 notify-keyspace-events 的参数可以是以下字符的 任意组合 , 它指定了服务器该发送哪些类型的通知。 字符 发送的通知 K 键空间通知,所有通知以 keyspace@ 为前缀 E 键事件通知,所有通知以

    2024年02月20日
    浏览(40)
  • 【SpringBoot笔记34】Spring Events事件驱动编程之事件的发布和监听操作

    这篇文章,主要介绍Spring Events事件驱动编程之事件的发布和监听操作。 目录 一、基于接口实现 1.1、自定义事件 1.2、主动发布事件 1.3、监听事件对象

    2024年02月16日
    浏览(45)
  • Spring高手之路15——掌握Spring事件监听器的内部逻辑与实现

    在阅读本文之前需要你已经对事件监听器有了简单的了解,或去阅读前面的文章《 Spring高手之路7——事件机制与监听器的全面探索 》   在 Spring 中, ApplicationContext 可以形成一个层次结构,通常由主容器和多个子容器组成。一个常见的疑问是:当一个事件在其中一个容器

    2024年02月06日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包