Spring 观察者模式详解以及自定义监听器扩展实现(下)

简介: Spring 观察者模式详解以及自定义监听器扩展实现(下)

SpringBoot 监听器加载过程

首先加载 META-INF/spring.factories 文件中的 key:ApplicationListener,value:全限定类名,然后获取到所有的实例存入 ApplicationContext 中,方便后续创建多播器对象时可以获取到这些监听器实例,注入:ApplicationContext 实例以后,就可以调用它来进行事件发布动作

通过观察以上内置监听器的源码,可以发现在这些监听器里都实现了 ApplicationListener 同时会使用到抽象类 ApplicationEvent,但这些内置监听器中的事件都是基于它抽象的实现,定义自己的事件类

事件驱动机制是基于观察者设计模式的实现,通过 ApplicationEvent 类、ApplicationListener 接口,可以通过 ApplicationContext 实现事件的发布

如下图整理了 SpringBoot 内置的监听器和事件:

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

前戏: 在事件准备发布时,首先会通过 getRunListeners 方法来获取我们在 META-INF/spring.factories 文件中的定义 SpringApplicationRunListener 接口实现类 EventPublishingRunListener,同时会完成该类的实例化操作,调用构造方法时,会初始化多路广播器对象:SimpleApplicationEventMulticaster,同时从上下文获取到前面加载好的 11 个监听器,进行绑定操作.

前戏工作做完以后,就到了发布事件的时候了

SimpleApplicationEventMulticaster#multicastEvent:在容器启动时会调用 listener#starting 方法(事件名:ApplicationStartingEvent)、环境对象准备前会调用 listener#environmentPrepared(事件名:ApplicationEnvironmentPreparedEvent)

以 ConfigFileApplicationListener 为例,会在其内部处理配置文件的解析工作,接受 ApplicationEnvironmentPreparedEvent 事件的处理,源码如下:

public void onApplicationEvent(ApplicationEvent event) {
      if (event instanceof ApplicationEnvironmentPreparedEvent) {
          this.onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent)event);
      }
      if (event instanceof ApplicationPreparedEvent) {
          this.onApplicationPreparedEvent(event);
      }
  }

自定义监听器扩展实现

通过几个不同类型自定义事件案例来加深对事件驱动机制的理解

监听所有事件

先创建一个自定义监听器,来监听所有的事件;创建一个 Java 类,实现 ApplicationListener 接口在泛型中指定要监听的事件类型即可,如果要监听所有的事件,那么泛型就写 ApplicationEvent

public class MySpringApplicationListener implements ApplicationListener<ApplicationEvent> {
  @Override
  public void onApplicationEvent(ApplicationEvent event) {
    System.out.println("自定义监听器--->" + event);
  }
}

之后为了在容器启动中能够发现我们的监听器并且添加到 SimpleApplicationEventMulticaster 中,我们需要在 spring.factories/META-INF 中注册自定义的监听器

org.springframework.context.ApplicationListener=\
com.vnjohn.demo.listener.MySpringApplicationListener

这样当我们启动服务的时候就可以看到相关事件发布,我们的监听器被触发了,会打印对应的信息

监听特定事件

如果是监听特定的事件,我们只需要在泛型出指定类型即可

public class MySpringApplicationStartingListener implements ApplicationListener<ApplicationStartingEvent> {
  @Override
  public void onApplicationEvent(ApplicationStartingEvent event) {
    // 该事件是启动启动时就会进行发布的,查询容器启动日志信息即可 
    System.out.println("MySpringApplicationStartingListener--------->" + event);
  }
}
org.springframework.context.ApplicationListener=\
com.vnjohn.demo.listener.MySpringApplicationListener,\
com.vnjohn.demo.listener.MySpringApplicationStartingListener

启动服务时可以看到相关的事件发布

自定义事件

若我们想要通过自定义的监听器来监听自定义的事件呢?首先创建自定义的事件类,非常简单,只需要继承 ApplicationEvent 即可

public class MyEvent extends ApplicationEvent {
  public MyEvent(Object source) {
    super(source);
  }
}

然后在自定义的监听器中监听自定义的事件

public class MyCustomerEventListener implements ApplicationListener<MyEvent> {
  @Override
  public void onApplicationEvent(MyEvent event) {
    System.out.println("MyCustomerEventListener ---》自定义事件触发" + event);
    // 触发对应的事件后 业务处理
    new Thread(()->{
      // 业务....
    }).start();
  }
}

事件的监听和发布是同步执行的,如果想让其异步的进行,可以抛给一个线程进行处理

org.springframework.context.ApplicationListener=\
com.vnjohn.demo.listener.MySpringApplicationListener,\
com.vnjohn.demo.listener.MySpringApplicationStartingListener,\
com.vnjohn.demo.listener.MyCustomerEventListener

之后我们就可以在我们特定的业务场景中类发布对应的事件了

@Component
public class MyApplicationContextAware implements ApplicationContextAware {
  private static ApplicationContext applicationContext;
  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    MyApplicationContextAware.applicationContext = applicationContext;
  }
  public static void publishEvent(ApplicationEvent applicationEvent) {
    applicationContext.publishEvent(applicationEvent);
  }
}
@RestController
public class HelloController {
  @GetMapping("/hello")
  public String hello(){
    MyApplicationContextAware.publishEvent(new MyEvent(new Object()));
    return "hello---";
  }
}

当提交请求后,对应的监听器就触发了,这样一来不光搞清楚了 SpringBoot 中的监听机制,而且也可以扩展使用到我们业务开发中了

总结

希望对你有所帮助,您的支持是对我最大的鼓励,关注+赞+收藏三连,感谢!

如果觉得博文不错,关注我 vnjohn,后续会有更多实战、源码、架构干货分享!

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!

目录
相关文章
|
13天前
|
Java Spring
Java Spring Boot监听事件和处理事件
通过上述步骤,我们可以在Java Spring Boot应用中实现事件的发布和监听。事件驱动模型可以帮助我们实现组件间的松耦合,提升系统的可维护性和可扩展性。无论是处理业务逻辑还是系统事件,Spring Boot的事件机制都提供了强大的支持和灵活性。希望本文能为您的开发工作提供实用的指导和帮助。
65 15
|
25天前
|
XML Java 数据格式
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
本文介绍了在使用Spring框架时,如何通过创建`applicationContext.xml`配置文件来管理对象。首先,在resources目录下新建XML配置文件,并通过IDEA自动生成部分配置。为完善配置,特别是添加AOP支持,可以通过IDEA的Live Templates功能自定义XML模板。具体步骤包括:连续按两次Shift搜索Live Templates,配置模板内容,输入特定前缀(如spring)并按Tab键即可快速生成完整的Spring配置文件。这样可以大大提高开发效率,减少重复工作。
使用idea中的Live Templates自定义自动生成Spring所需的XML配置文件格式
|
25天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
1月前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
100 14
|
1月前
|
缓存 安全 Java
Spring高手之路26——全方位掌握事务监听器
本文深入探讨了Spring事务监听器的设计与实现,包括通过TransactionSynchronization接口和@TransactionalEventListener注解实现事务监听器的方法,并通过实例详细展示了如何在事务生命周期的不同阶段执行自定义逻辑,提供了实际应用场景中的最佳实践。
52 2
Spring高手之路26——全方位掌握事务监听器
|
2月前
|
安全 Java 应用服务中间件
如何将Spring Boot应用程序运行到自定义端口
如何将Spring Boot应用程序运行到自定义端口
78 0
|
3月前
|
设计模式 Java Spring
Spring Boot监听器的底层实现原理
Spring Boot监听器的底层实现原理主要基于观察者模式(也称为发布-订阅模式),这是设计模式中用于实现对象之间一对多依赖的一种常见方式。在Spring Boot中,监听器的实现依赖于Spring框架提供的事件监听机制。
56 1
|
4月前
|
消息中间件 设计模式 缓存
spring源码设计模式分析(四)-观察者模式
spring源码设计模式分析(四)-观察者模式
|
5月前
|
监控 安全 Java
【开发者必备】Spring Boot中自定义注解与处理器的神奇魔力:一键解锁代码新高度!
【8月更文挑战第29天】本文介绍如何在Spring Boot中利用自定义注解与处理器增强应用功能。通过定义如`@CustomProcessor`注解并结合`BeanPostProcessor`实现特定逻辑处理,如业务逻辑封装、配置管理及元数据分析等,从而提升代码整洁度与可维护性。文章详细展示了从注解定义、处理器编写到实际应用的具体步骤,并提供了实战案例,帮助开发者更好地理解和运用这一强大特性,以实现代码的高效组织与优化。
274 0
|
5月前
|
存储 Java API