• ApplicationListener和@EventListener


    前言

    在开发工作中,会遇到一种场景,做完某一件事情以后,需要广播一些消息或者通知,告诉其他的模块进行一些事件处理,一般来说,可以一个一个发送请求去通知,但是有一种更好的方式,那就是事件监听,事件监听也是设计模式中 发布-订阅模式、观察者模式的一种实现。

    观察者模式:简单的来讲就是你在做事情的时候身边有人在盯着你,当你做的某一件事情是旁边观察的人感兴趣的事情的时候,他会根据这个事情做一些其他的事,但是盯着你看的人必须要到你这里来登记,否则你无法通知到他(或者说他没有资格来盯着你做事情)。

    对于 Spring 容器的一些事件,可以监听并且触发相应的方法。通常的方法有 2 种,ApplicationListener 接口和**@EventListener** 注解。一个作用在类上,一个作用在方法上。

    概念:

    要想顺利的创建监听器,并起作用,这个过程中需要这样几个角色:
    1、事件(event)可以封装和传递监听器中要处理的参数,如对象或字符串,并作为监听器中监听的目标。
    2、监听器(listener)具体根据事件发生的业务处理模块,这里可以接收处理事件中封装的对象或字符串。
    3、事件发布者(publisher)事件发生的触发者。

    实现ApplicationListener 接口

    原生事件

    @Component
    public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
     
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
      System.out.println("事件触发:"+event.getClass().getName());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    @SpringBootApplication
    public class ApplicationListenerDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ApplicationListenerDemoApplication.class, args);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    事件触发:org.springframework.context.event.ContextRefreshedEvent
    2021-01-24 22:09:20.113  INFO 9228 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    事件触发:org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent
    2021-01-24 22:09:20.116  INFO 9228 --- [           main] c.n.ApplicationListenerDemoApplication   : Started ApplicationListenerDemoApplication in 1.221 seconds (JVM running for 1.903)
    事件触发:org.springframework.boot.context.event.ApplicationStartedEvent
    事件触发:org.springframework.boot.context.event.ApplicationReadyEvent
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    自定义事件

    事件

    public class MyTestEvent extends ApplicationEvent{
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
    
        private String msg ;
    
        public MyTestEvent(Object source,String msg) {
            super(source);
            this.msg = msg;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    监听器

    @Component
    public class MyNoAnnotationListener implements ApplicationListener<MyTestEvent> {
    
        @Override
        public void onApplicationEvent(MyTestEvent event) {
            System.out.println("非注解监听器:" + event.getMsg());
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    事件发布

    @Component
    public class MyTestEventPubLisher {
        @Autowired
        private ApplicationEventPublisher applicationEventPublisher;
    
        /**
         *  事件发布方法
          */
        public void pushListener(String msg) {
            applicationEventPublisher.publishEvent(new MyTestEvent(this, msg));
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    测试

    @RestController
    public class TestEventListenerController {
    
        @Autowired
        private MyTestEventPubLisher publisher;
    
        @RequestMapping(value = "/test/testPublishEvent1" )
        public void testPublishEvent(){
            publisher.pushListener("我来了!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出:

    事件触发:com.njit.personal.unannotation.MyTestEvent
    非注解监听器:我来了!
    
    • 1
    • 2

    @EventListener 注解

    原生事件

    @Configuration
    public class Config {
        @EventListener(classes = {ApplicationEvent.class})
        public void listen(ApplicationEvent event) {
            System.out.println("事件触发:" + event.getClass().getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    启动项目:

    事件触发:org.springframework.context.event.ContextRefreshedEvent
    2021-01-24 22:39:13.647  INFO 16072 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    事件触发:org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent
    2021-01-24 22:39:13.650  INFO 16072 --- [           main] c.n.ApplicationListenerDemoApplication   : Started ApplicationListenerDemoApplication in 1.316 seconds (JVM running for 2.504)
    事件触发:org.springframework.boot.context.event.ApplicationStartedEvent
    事件触发:org.springframework.boot.context.event.ApplicationReadyEvent
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    自定义事件

    监听器

    //事件和发布还是使用上边的
    @Component
    public class MyAnnotationListener {
    
        @EventListener
        public void listener1(MyTestEvent event) {
            System.out.println("注解监听器1:" + event.getMsg());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    事件触发:com.njit.personal.unannotation.MyTestEvent
    注解监听器1:我来了!
    非注解监听器:我来了!
    
    • 1
    • 2
    • 3

    项目常用

    @EventListener(AvailabilityChangeEvent.class)
    public void init(AvailabilityChangeEvent<ReadinessState> event) {
       //项目启动会触发监听器,下面写一些业务逻辑
       ....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    或者

    @Component
    public class MyApplicationListener implements ApplicationListener {
     
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
       //项目启动会触发监听器,下面写一些业务逻辑
       ....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    参考:

    https://segmentfault.com/a/1190000039097608

  • 相关阅读:
    【基础】性能测试,从0到实战(手把手教,非常实用)
    怎么将两个PDF合并成一个?这里有三个小妙招分享给你
    小白学习Java第四十天
    NLP(2)--搭建简单的模型(nn)
    Flink应用
    容器是什么?
    管理信息系统期末复习资料
    VR钢铁实训 | 铁前事业部虚拟仿真培训软件
    linux系统 常用命令(全面总结)
    设计模式之桥梁模式
  • 原文地址:https://blog.csdn.net/weixin_43604021/article/details/126473818