ApplicationListener使用

房东的猫 提交于 2020-03-19 12:04:54

3 月,跳不动了?>>>

1. 介绍

Spring有两大类事件 ,一类是 Application事件,超类是SpringApplicationEvent, 这类事件是在Spring程序启动时,每执行到一个阶段就发出一个事件,依次对应ApplicationStartingEvent到ApplicationReadyEvent,表示spring程序从启动开始到启动完成的过程。当然还有一个如果在启动过程中出现异常,就会发出 ApplicationFailedEvent  事件。 

另一类是ApplicationContext事件,超类是 ApplicationContextEvent ,这类事件 表示ApplicationContext生命周期内的各个阶段 

2. 内置事件

其中spring有一些内置的事件,当完成某种操作时会发出某些事件动作。

ApplicationContext内置事件

序号 内置事件 描述
1 ContextRefreshedEvent ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用
2 ContextStartedEvent 当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。
3 ContextStoppedEvent 当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
4 ContextClosedEvent 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启

SpringApplicationEvent内置事件:

前5种事件,是Spring按照启动前后顺序,依次生成的。我们想要监听启动之前的事件和启动完成的事件,只需关注ApplicationStartingEvent和ApplicationReadyEvent

序号 内置事件 描述
1

ApplicationStartingEvent

除了基础的注册监听和初始化之外,在开始运行时做任何处理动作之前发送
2

ApplicationEnvironmentPreparedEvent 

在上下文中使用的环境已知,但是Context尚未创建之前发送
3

ApplicationPreparedEvent 

在Spring刷新Context开始之前,而仅当加载bean定义之后发送
4

ApplicationStartedEvent 

在刷新上下文之后,但在调用任何应用程序(ApplicationRunner)和命令行运行程序(CommandLineRunner)之前发送
5

ApplicationReadyEvent 

在调用应用程序和命令行运行程序后发送。 它表示应用程序已准备好为请求提供服务。
6

ApplicationFailedEvent 

在启动过程中出现异常时发送。

RequestHandledEvent内置事件:这是一个特定web事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。

序号 内置事件 描述
1 ServletRequestHandledEvent 包含特定请求上下文的信息

ApplicationEvent继承关系

 

3. 内置事件的使用和执行时机

内置事件的执行官方提供了两种方式

第一种:通过SPI扩展方式 META-INF/spring.factories中添加配置ApplicationListener

# Initializer
org.springframework.context.ApplicationContextInitializer=\
com.example.demo.initializer.TestApplicationContextInitializer

# Application Listeners
org.springframework.context.ApplicationListener=\
com.example.demo.listener.TestApplicationListener

TestApplicationListener 类实现接口ApplicationListener,泛型参数为ApplicationEvent时则监听所有类型的内置事件。如果要监听指定类型的内置事件,可转入指定Event类即可,如:要监听ApplicationContext刷新事件则可以只监听ContextRefreshedEvent。

public class TestApplicationListener implements ApplicationListener<ApplicationEvent>{

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("执行ApplicationEvent事件:"+event.getClass().getSimpleName());
    }

}

执行结果:可以看到每种事件发出的时机和顺序

执行ApplicationEvent事件:ApplicationStartingEvent
执行ApplicationEvent事件:ApplicationEnvironmentPreparedEvent

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.5.RELEASE)

Initializer调用:
执行ApplicationEvent事件:ApplicationContextInitializedEvent
2020-03-19 09:40:42.694  INFO 93896 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on ZZ-WZ112019 with PID 93896 (E:\java_work\demo\target\classes started by jiafeng in E:\java_work\demo)
2020-03-19 09:40:42.696  INFO 93896 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
执行ApplicationEvent事件:ApplicationPreparedEvent
执行ApplicationEvent事件:ContextRefreshedEvent
2020-03-19 09:40:42.978  INFO 93896 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.525 seconds (JVM running for 0.834)
执行ApplicationEvent事件:ApplicationStartedEvent
执行ApplicationEvent事件:ApplicationReadyEvent
启动完成
执行ApplicationEvent事件:ContextClosedEvent

第二种:在启动类里面 添加监听器

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        //SpringApplication.run(DemoApplication.class, args);
        SpringApplication application = new SpringApplication(DemoApplication.class);
        application.addListeners(new TestApplicationListener()); //添加监听器
        application.run(args);
        System.out.println("启动完成");
    }

}

或者SpringApplicationBuilder类添加监听器

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        //SpringApplication.run(DemoApplication.class, args);
//        SpringApplication application = new SpringApplication(DemoApplication.class);
//        application.addListeners(new TestApplicationListener()); //添加监听器
//        application.run(args);
        
        new SpringApplicationBuilder(DemoApplication.class)
        .listeners(new TestApplicationListener()) //添加监听器
        .run(args);
        
        
        
        System.out.println("启动完成");
    }

}

执行结果:跟SIP方式执行结果相同

执行ApplicationEvent事件:ApplicationStartingEvent
执行ApplicationEvent事件:ApplicationEnvironmentPreparedEvent

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.5.RELEASE)

Initializer调用:
执行ApplicationEvent事件:ApplicationContextInitializedEvent
2020-03-19 10:00:24.874  INFO 99744 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on ZZ-WZ112019 with PID 99744 (E:\java_work\demo\target\classes started by jiafeng in E:\java_work\demo)
2020-03-19 10:00:24.875  INFO 99744 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
执行ApplicationEvent事件:ApplicationPreparedEvent
执行ApplicationEvent事件:ContextRefreshedEvent
2020-03-19 10:00:25.153  INFO 99744 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.515 seconds (JVM running for 0.829)
执行ApplicationEvent事件:ApplicationStartedEvent
执行ApplicationEvent事件:ApplicationReadyEvent
启动完成
执行ApplicationEvent事件:ContextClosedEvent

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!