Spring 事件机制

简介: 在一个完整的事件体系中、存在以下的角色1. 事件:描述发生了什么事情、比如说请求处理完成、Spring 容器刷新完毕2. 事件源:事件的产生者、任何一个事件都必须有一个事件源。比如请求处理完成的事件源就是 DispatcherServlet 、Spring 容器刷新完毕的事件源就是 ApplicationContext3. 事件广播器:事件和事件监听器的桥梁、负责把事件通知给事件监听器4. 事件监听器:监听事件的发生、可以在监听器中做一些处理

网络异常,图片无法展示
|


概念


在一个完整的事件体系中、存在以下的角色

  1. 事件:描述发生了什么事情、比如说请求处理完成、Spring 容器刷新完毕
  2. 事件源:事件的产生者、任何一个事件都必须有一个事件源。比如请求处理完成的事件源就是 DispatcherServlet 、Spring 容器刷新完毕的事件源就是 ApplicationContext
  3. 事件广播器:事件和事件监听器的桥梁、负责把事件通知给事件监听器
  4. 事件监听器:监听事件的发生、可以在监听器中做一些处理


Spring 事件

网络异常,图片无法展示
|


我们常见的事件可能就是 ApplicationContextEvent 、它的子类 ContextRefreshedEvent 是我们常见的事件类型、在 Spring 将所有非延迟加载的 bean 实例化之后发布。

网络异常,图片无法展示
|


再来看看 Spring 事件的体系结构

网络异常,图片无法展示
|


Spring 监听器

网络异常,图片无法展示
|


事件广播器

网络异常,图片无法展示
|

网络异常,图片无法展示
|


ApplicationContext 对事件的支持

网络异常,图片无法展示
|

ApplicationEventPublisher 这个是 Spring 提供给用户使用的一个事件发布器啊、真正实现发布功能还是委托给上面的 ApplicationEventMulticaster 去实现的。

Spring 提供了 ApplicationEventPublisherAware 让用户可以去获取这个发布器进行事件发布。


使用方式

Spring 提供了两种方式

  1. 实现 ApplicationListener 接口
  2. 使用注解 @EventListener


注解的实现源码

我们直接看到 EventListenerMethodProcessor 该类实现了接口 SmartInitializingSingleton 接口、该接口会在 Spring 初始化完所有的非延迟加载的 bean 之后被调用。

public interface SmartInitializingSingleton {
    /**
     * Invoked right at the end of the singleton pre-instantiation phase,
     * with a guarantee that all regular singleton beans have been created
     * already. {@link ListableBeanFactory#getBeansOfType} calls within
     * this method won't trigger accidental side effects during bootstrap.
     * <p><b>NOTE:</b> This callback won't be triggered for singleton beans
     * lazily initialized on demand after {@link BeanFactory} bootstrap,
     * and not for any other bean scope either. Carefully use it for beans
     * with the intended bootstrap semantics only.
     */
    void afterSingletonsInstantiated();
 }
复制代码

网络异常,图片无法展示
|


其实实现逻辑非常简单

for (Method method : annotatedMethods.keySet()) {
    for (EventListenerFactory factory : factories) {
       if (factory.supportsMethod(method)) {
          Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
          ApplicationListener<?> applicationListener =
                factory.createApplicationListener(beanName, targetType, methodToUse);
          if (applicationListener instanceof ApplicationListenerMethodAdapter) {
             ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
          }
          context.addApplicationListener(applicationListener);
          break;
       }
    }
 }
复制代码


找出所有被注解修饰的方法、然后分别创建一个对应的 ApplicationListener、收到事件后反射调用该方法。

public void processEvent(ApplicationEvent event) {
    Object[] args = resolveArguments(event);
    if (shouldHandle(event, args)) {
       Object result = doInvoke(args);
       if (result != null) {
          handleResult(result);
       }
       else {
          logger.trace("No result object given - no result to handle");
       }
    }
 }
复制代码


监听器调用的先后顺序

我们可以在 AbstractApplicationEventMulticaster#retrieveApplicationListeners 中看到是支持我们指定监听器的顺序的、Spring 很多涉及顺序的都可以使用

  1. 实现 Ordered 接口
  2. 实现 PriorityOrdered 接口
  3. 使用 @Ordered 接口


异步调用监听器

默认情况下、Spring 创建的事件广播器是采用同步方式调用通知监听器的、我们可以设置或者替换 Spring 默认的监听器来达到异步调用的目的、当然也可以扩展、根据事件的不同采用同步或者异步的方式、而不是单一的要么所有同步要么所有异步

@Override
 public void multicastEvent(final 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);
       }
    }
 }
复制代码


Spring refresh 之前回初始化事件传播器

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() + "]");
       }
    }
 }
复制代码


替换原来的事件传播器

@Component("applicationEventMulticaster")
 public class TestEventMulticaster extends SimpleApplicationEventMulticaster {
 }



目录
打赏
0
0
0
0
1
分享
相关文章
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
141 2
|
1月前
|
Spring 手动实现Spring底层机制
Spring 第六节 手动实现Spring底层机制 万字详解!
78 31
|
2月前
|
Java Spring Boot监听事件和处理事件
通过上述步骤,我们可以在Java Spring Boot应用中实现事件的发布和监听。事件驱动模型可以帮助我们实现组件间的松耦合,提升系统的可维护性和可扩展性。无论是处理业务逻辑还是系统事件,Spring Boot的事件机制都提供了强大的支持和灵活性。希望本文能为您的开发工作提供实用的指导和帮助。
112 15
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
198 14
Spring框架中的事件机制:深入理解与实践
Spring框架是一个广泛使用的Java企业级应用框架,提供了依赖注入、面向切面编程(AOP)、事务管理、Web应用程序开发等一系列功能。在Spring框架中,事件机制是一种重要的通信方式,它允许不同组件之间进行松耦合的通信,提高了应用程序的可维护性和可扩展性。本文将深入探讨Spring框架中的事件机制,包括不同类型的事件、底层原理、应用实践以及优缺点。
95 8
深入探讨:Spring与MyBatis中的连接池与缓存机制
Spring 与 MyBatis 提供了强大的连接池和缓存机制,通过合理配置和使用这些机制,可以显著提升应用的性能和可扩展性。连接池通过复用数据库连接减少了连接创建和销毁的开销,而 MyBatis 的一级缓存和二级缓存则通过缓存查询结果减少了数据库访问次数。在实际应用中,结合具体的业务需求和系统架构,优化连接池和缓存的配置,是提升系统性能的重要手段。
166 4
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
117 8
Spring IoC容器通过依赖注入机制实现控制反转
【4月更文挑战第30天】Spring IoC容器通过依赖注入机制实现控制反转
83 0
Spring的Factories机制介绍
Spring的Factories机制介绍
146 1
Spring 框架事件发布与监听机制,如魔法风暴席卷软件世界,开启奇幻编程之旅!
【8月更文挑战第31天】《Spring框架中的事件发布与监听机制》介绍了Spring中如何利用事件发布与监听机制实现组件间的高效协作。这一机制像城市中的广播系统,事件发布者发送消息,监听器接收并响应。通过简单的示例代码,文章详细讲解了如何定义事件类、创建事件发布者与监听器,并确保组件间松散耦合,提升系统的可维护性和扩展性。掌握这一机制,如同拥有一把开启高效软件开发大门的钥匙。
64 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等