Spring中的ApplicationListener以及观察者模式

Spring中的ApplicationListener以及观察者模式

1.介绍

在之前的文章从SpringBoot启动过程分析到自定义一个springboot-starter中我们看到了Spring监听器在SpringApplication得启动过程中扮演了相当重要的角色,
在SpringApplication初始化和ConfigurableApplicationContext创建的不同阶段通过发布相应类型的事件,不同的ApplicationListener监听到相应的Event执行从而完成了自己对应的一些初始化操作。

2.spring内置的ApplicationListener分析

SpringBoot2.3.3中spring.factories中内置了如下的ApplicationListener:

 # Application Listeners
 org.springframework.context.ApplicationListener=\
 org.springframework.boot.ClearCachesApplicationListener,\
 org.springframework.boot.builder.ParentContextCloserApplicationListener,\
 org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
 org.springframework.boot.context.FileEncodingApplicationListener,\
 org.springframework.boot.context.config.AnsiOutputApplicationListener,\
 org.springframework.boot.context.config.ConfigFileApplicationListener,\
 org.springframework.boot.context.config.DelegatingApplicationListener,\
 org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
 org.springframework.boot.context.logging.LoggingApplicationListener,\
 org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

来看下其中一些主要的listener的作用:

ApplicationListener 作用 监听事件
ClearCachesApplicationListener 上下文环境context加载后清理缓存 ContextRefreshedEvent
ParentContextCloserApplicationListener 如果父对象关闭,则关闭应用程序上下文 ParentContextAvailableEvent
FileEncodingApplicationListener 当系统属性file.encoding与spring的强制编码属性spring.mandatory-file-encoding不一致时,打印信息,并抛出IllegalStateException异常 ApplicationEnvironmentPreparedEvent
AnsiOutputApplicationListener 根据属性spring.output.ansi.enabled来配置ANSI输出 ApplicationEnvironmentPreparedEvent
ConfigFileApplicationListener 搜索并加载配置文件,根据配置文件设置Environment和SpringApplication ApplicationEnvironmentPreparedEvent & ApplicationPreparedEvent
DelegatingApplicationListener 类似于DelegatingApplicationContextInitializer的作用,加载并转发配置在context.listener.classes属性的其它ApplicationListener ApplicationEvent
ClasspathLoggingApplicationListener 在DEBUG日志级别下,对ApplicationEnvironmentPreparedEvent和ApplicationFailedEvent打印相应的日志 ApplicationEvent
LoggingApplicationListener 根据配置,在合适的时候初始化和配置系统日志 ApplicationEvent

3.ApplicationListener事件监听机制的使用

事件的发布和监听涉及到三个部分:

  • 事件发布方:spring中的事件发布最终是由 SimpleApplicationEventMulticaster 类中的multicastEvent进行发布操作。一般使用时直接使用ApplicationContext发布即可。
  • event事件:可以通过继承 ApplicationEvent 自定义要接收的event类型
  • 事件接收方:自定义事件监听器listener来监听发布的事件从而执行相应的操作,以下两种方式可以定义listener:
    • 实现ApplicationListener接口并指定要监听的事件类型
    @Component
    public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
        
        Logger log = LoggerFactory.getLogger(MyApplicationListener.class);
        
        public void onApplicationEvent(MyApplicationEvent event) {
            log.info("监听到event:{}",event);
        }
    }
    
    • 使用 @EventListener设置监听方法,比较简便,无需单独创建监听类
    @Component
    public class MyApplicationListener1 {
    
        Logger log = LoggerFactory.getLogger(MyApplicationListener1.class);
    
        @EventListener
        public void onApplicationEvent(MyApplicationEvent event) {
            log.info("监听到event:{}",event);
        }
    }
    

4.从观察者模式分析监听器机制

  • 观察者模式:定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新 对象行为型模式
    • 角色:
      • abstractSubject: 抽象主题(抽象被观察者)
        保持观察者的列表,有权增删观察者,发生变化时通知观察者
      • concreteSubject: 具体被观察者 实现具体的改变,并在发生改变时 通知具体的观察者
      • abstractObserver: 抽象观察者 定义update()接口,即收到主题通知后的操作
      • concreteObserver: 具体观察者 实现update()接口,保持与主题的改变相符合的状态
    • 推模型和拉模型
      • 推模型: push 由subject主题对象主动向观察者推送改变的数据(存在的问题,主题对象不知道观察者需要哪些数据时,只能推送所有)
      • 拉模型: pull 主题对象仅推送少量信息,通过传递subject引用给观察者,观察者自己选择需要获取的数据
    • java中对观察者模式的支持
      • Observer接口:
        update()方法,当被观察者对象的状态发生变化时,被观察者对象的notifyObservers()方法就会调用这一方法
      • Observable 类:被观察者类都是java.util.Observable类的子类
        setChanged():被调用之后会设置一个内部标记变量,代表被观察者对象的状态发生了变化
        notifyObservers():这个方法被调用时,会调用所有登记过的观察者对象的update()方法,使这些观察者对象可以更新自己。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。