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<AvailabilityChangeEvent> {
 
@Override
public void onApplicationEvent(ApplicationEvent event) {
   //项目启动会触发监听器,下面写一些业务逻辑
   ....
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

参考:

https://segmentfault.com/a/1190000039097608

 https://zhuanlan.zhihu.com/p/620722589
posted @ 2023-04-10 14:15  甜菜波波  阅读(198)  评论(0编辑  收藏  举报