首页 > 技术文章 > springboot 的事件监听

abiu 2021-09-23 21:48 原文

测试代码:https://gitee.com/wangbiao666/springboot-listener.git

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

简介

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

简单使用

使用方法很简单,就是实现一个 ApplicationListener 接口,并且将加入到容器中就行。

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * 简单使用监听,只需要实现ApplicationListener
 */
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        // 启动项目就触发
        System.out.println("事件触发:================" + event.getClass().getName());
    }
}

然后启动自己的springboot项目,可以看到控制台输出
image

自定义事件以及监听

定义事件

首先,我们需要定义一个时间(MyTestEvent),需要继承Spring的ApplicationEvent

import org.springframework.context.ApplicationEvent;

/**
 * 自定义时间监听器
 */
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;
    }
}

定义监听器

需要定义一下监听器,自己定义的监听器需要实现ApplicationListener,同时泛型参数要加上自己要监听的事件Class名,在重写的方法onApplicationEvent中,添加自己的业务处理:

import com.test.listener.event.MyTestEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyNoAnnotationListener implements ApplicationListener<MyTestEvent> {

    @Override
    public void onApplicationEvent(MyTestEvent event) {
        System.out.println("非注解监听器:===========" + event.getMsg());
    }

}

事件发布

有了事件,有了事件监听者,那么什么时候触发这个事件呢?每次想让监听器收到事件通知的时候,就可以调用一下事件发布的操作。首先在类里自动注入了ApplicationEventPublisher,这个也就是我们的ApplicationCOntext,它实现了这个接口。

import com.test.listener.event.MyTestEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

@Component
public class MyTestEventPubLisher {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    /**
     *  事件发布方法
      */
    public void pushListener(String msg) {
        applicationEventPublisher.publishEvent(new MyTestEvent(this, msg));
    }
}

测试

用一个HTTP请求来模拟:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestEventListenerController {

    @Autowired
    private MyTestEventPubLisher publisher;

    @RequestMapping(value = "/test/testPublishEvent1" )
    public void testPublishEvent(){
        publisher.pushListener("我来了!");
    }
}

启动项目,请求测试接口
image
控制台打印
image

@EventListener 注解

简单使用

除了通过实现接口,还可以使用@EventListener 注解,实现对任意的方法都能监听事件。

在任意方法上标注@EventListener 注解,指定 classes,即需要处理的事件类型,一般就是 ApplicationEven 及其子类,可以设置多项。

import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;

@Configuration
public class Config {
    @EventListener(classes = {ApplicationEvent.class})
    public void listen(ApplicationEvent event) {
        System.out.println("注解的事件触发:==========" + event.getClass().getName());
    }
}

启动项目
可以看到控制台
image

自定义事件以及监听

使用注解的好处是不用每次都去实现ApplicationListener,可以在一个class中定义多个方法,用@EventListener来做方法级别的注解。

和上面类似,事件以及事件发布不需要改变,只要这样定义监听器即可。

import com.test.listener.event.MyTestEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyAnnotationListener {

    @EventListener
    public void listener1(MyTestEvent event) {
        System.out.println("注解监听器:==================" + event.getMsg());
    }
}

启动项目,触发测试请求接口
image

推荐阅读