Spring中自定义事件原理

简介: Spring中自定义事件原理
  1. Spring中所有的事件监听器实现ApplicationListener.onApplicationEvent(E event)方法
  2. Spring容器会在启动的过程中获取所有的监听器对象,并持有,当有事件被抛出时,就会轮询所有监听这个事件的监听器进行处理。

通过源码理解过程:

  protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
      ApplicationEvent applicationEvent;
      if (event instanceof ApplicationEvent) {
          applicationEvent = (ApplicationEvent) event;
      }
      else {
          //封装成applicationEvent
          applicationEvent = new PayloadApplicationEvent<>(this, event);
          if (eventType == null) {
              eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
          }
      }
      // Multicast right now if possible - or lazily once the multicaster is initialized
      if (this.earlyApplicationEvents != null) {
          //监听器在注册到容器之前累积的事件,监听器注册完成之后会消耗掉这些事件,并将earlyApplicationEvents置空
          this.earlyApplicationEvents.add(applicationEvent);
      }
      else {//进行事件广播
          getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
      }

      //将事件抛给父容器
      // Publish event via parent context as well...
      if (this.parent != null) {
          if (this.parent instanceof AbstractApplicationContext) {
              ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
          }
          else {
              this.parent.publishEvent(event);
          }
      }
  }

SimpleApplicationEventMulticaster事件广播器

  //广播事件
  public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
      ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
      for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
          Executor executor = getTaskExecutor();
          if (executor != null) {//通过线程池处理
              executor.execute(() -> invokeListener(listener, event));
          }
          else {//在当前线程处理
              invokeListener(listener, event);
          }
      }
  }

  //处理事件
  private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
      //调用监听器的方法进行处理
      listener.onApplicationEvent(event);
  }
  1. 监听器的创建过程
    EventListenerMethodProcessor对象会在容器中的对象实例化完成后,会对有@EventListener注解的方法进行代理,并创建相应的监听器。

具体看EventListenerMethodProcessor.processBean()方法

protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {

    if (!this.nonAnnotatedClasses.contains(targetType)) {
        Map<Method, EventListener> annotatedMethods = null;
        try {
            //找到有@EventListener注解的方法
            annotatedMethods = MethodIntrospector.selectMethods(targetType,
                    (MethodIntrospector.MetadataLookup<EventListener>) method ->
                            AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
        }
        catch (Throwable ex) {
            // An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
            if (logger.isDebugEnabled()) {
                logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
            }
        }
        if (CollectionUtils.isEmpty(annotatedMethods)) {
            this.nonAnnotatedClasses.add(targetType);
            if (logger.isTraceEnabled()) {
                logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
            }
        }
        else {
            // Non-empty set of methods
            ConfigurableApplicationContext context = getApplicationContext();
            //轮询所有监听的方法
            for (Method method : annotatedMethods.keySet()) {
                //轮询所有的EventListenerFactory
                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中。
                        context.addApplicationListener(applicationListener);
                        break;//监听器不能重复,避免多个监听器工厂都支持同一个事件处理方法(工厂是排过序的)
                    }
                }
            }
            ......
        }
    }
}
目录
相关文章
|
3月前
|
缓存 Java 开发者
【Spring】原理:Bean的作用域与生命周期
本文将围绕 Spring Bean 的作用域与生命周期展开深度剖析,系统梳理作用域的类型与应用场景、生命周期的关键阶段与扩展点,并结合实际案例揭示其底层实现原理,为开发者提供从理论到实践的完整指导。
509 22
|
3月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
1316 0
|
2月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
2月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
426 2
|
4月前
|
Java 关系型数据库 数据库
深度剖析【Spring】事务:万字详解,彻底掌握传播机制与事务原理
在Java开发中,Spring框架通过事务管理机制,帮我们轻松实现了这种“承诺”。它不仅封装了底层复杂的事务控制逻辑(比如手动开启、提交、回滚事务),还提供了灵活的配置方式,让开发者能专注于业务逻辑,而不用纠结于事务细节。
|
8月前
|
存储 人工智能 自然语言处理
RAG 调优指南:Spring AI Alibaba 模块化 RAG 原理与使用
通过遵循以上最佳实践,可以构建一个高效、可靠的 RAG 系统,为用户提供准确和专业的回答。这些实践涵盖了从文档处理到系统配置的各个方面,能够帮助开发者构建更好的 RAG 应用。
3644 113
|
7月前
|
前端开发 Java 数据库连接
Spring核心原理剖析与解说
每个部分都是将一种巨大并且复杂的技术理念传达为更易于使用的接口,而这就是Spring的价值所在,它能让你专注于开发你的应用,而不必从头开始设计每一部分。
219 32
|
5月前
|
缓存 安全 Java
Spring 框架核心原理与实践解析
本文详解 Spring 框架核心知识,包括 IOC(容器管理对象)与 DI(容器注入依赖),以及通过注解(如 @Service、@Autowired)声明 Bean 和注入依赖的方式。阐述了 Bean 的线程安全(默认单例可能有安全问题,需业务避免共享状态或设为 prototype)、作用域(@Scope 注解,常用 singleton、prototype 等)及完整生命周期(实例化、依赖注入、初始化、销毁等步骤)。 解析了循环依赖的解决机制(三级缓存)、AOP 的概念(公共逻辑抽为切面)、底层动态代理(JDK 与 Cglib 的区别)及项目应用(如日志记录)。介绍了事务的实现(基于 AOP
190 0
|
5月前
|
监控 架构师 NoSQL
spring 状态机 的使用 + 原理 + 源码学习 (图解+秒懂+史上最全)
spring 状态机 的使用 + 原理 + 源码学习 (图解+秒懂+史上最全)
|
7月前
|
Java 开发者 Spring
Spring框架 - 深度揭秘Spring框架的基础架构与工作原理
所以,当你进入这个Spring的世界,看似一片混乱,但细看之下,你会发现这里有个牢固的结构支撑,一切皆有可能。不论你要建设的是一座宏大的城堡,还是个小巧的花园,只要你的工具箱里有Spring,你就能轻松搞定。
306 9

热门文章

最新文章