SpringBoot--事件&监听

311 阅读3分钟

详解

SpringBoot在启动过程中有一个事件监听机制。在启动的各个阶段,SpringBoot会发布一些事件,对应的监听器监听到事件后可以做相应处理。Spring中的事件编程模型是观察者设计模式的实现。用户可以自定义监听器监听事件,方便扩展。   

ApplicationListener

监听例子

import lombok.extern.log4j.Log4j2;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
/**
 * 实现ApplicationContext事件处理
 * ApplicationListener没有泛型,即监听所有ApplicationContext事件
 * ApplicationListener泛型可以是ApplicationEvent的各个实现
 * @author lord
 * @Date 2022/5/30 18:54
 */
@Log4j2
@Component
public class ApplicationContext implements ApplicationListener {
    public static int LOAD_ORDER = 0;//加载顺序
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        LOAD_ORDER++;
        log.info("监听ApplicationContext。第{}个加载:{}", LOAD_ORDER, event.getClass().getCanonicalName());
    }
}

打印结果

AAAAAAAAA.png

事件说明

ContextRefreshedEvent

ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用

ContextStartedEvent

当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。

ContextStoppedEvent

当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。

ContextClosedEvent

当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。

RequestHandledEvent

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

自定义事件&监听       

自定义事件

import org.springframework.context.ApplicationEvent;
 /**
 * 自定义事件
 * @author lord
 * @Date 2022/5/30 19:29
 */
 public class CustomEvent extends ApplicationEvent {
    private String event;//自定义属性
    //必须的构造器
    public CustomEvent(Object source) {
        super(source);
    }
    //自定义构造器
    public CustomEvent(Object source, String event) {
        super(source);
        this.event = event;
    }
    //自定义方法
    public String eventMsg(String msg) {
        return "CustomEvent被监听到,收到参数[" + msg + "],事件属性["+event+"]";
    }
}

自定义监听

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
 * 自定义监听  监听 CustomEvent
 * 启动类需要发布事件
 * @author lord
 * @Date 2022/5/30 19:55
 */
@Log4j2
@Component
public class CustomListenser implements ApplicationListener<CustomEvent> {
    /**
     * @return void
     * @Title onApplicationEvent
     * @author lord
     * @Description 编程式监听,需要实现 ApplicationListener<CustomEvent>
     * @Date 2022/5/30 20:09
     * @Param [event]
     */
    @Override
    public void onApplicationEvent(CustomEvent event) {
        log.info(event.eventMsg("ProgramListenser.onApplicationEvent监听到CustomEvent"));
    }
    /**
     * @return void
     * @Title annotationEvent
     * @author lord
     * @Description @EventListener 注解监听
     * 参数为 Object 类型时,所有事件都会监听到
     * 参数为指定类型事件时,该参数类型事件或者其子事件(子类)都可以接收到
     * @Date 2022/5/30 20:11
     * @Param [event]
     */
    @EventListener
    public void annotationEvent(CustomEvent event) {
        log.info(event.eventMsg("ProgramListenser.annotationEvent监听到CustomEvent"));
    }
}

启动类发布事件(boot启动时触发事件)

如此一来,则在boot启动时触发事件

import com.erpei.studysb.event.custom.CustomEvent;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class StudySpringbootApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =  SpringApplication.run(StudySpringbootApplication.class, args);
        //发布事件
        context.publishEvent(new CustomEvent(new Object(),"容器启动时触发自定义事件"));
    }
}

手动触发事件(SpringBoot实现观察者模式)

@SpringBootTest
@ExtendWith(SpringExtension.class)
class CustomEventTest {
    @Autowired
    private ApplicationContext applicationContext;
    @Test
    public void pushCustomEvent() {
        applicationContext.publishEvent(new CustomEvent(new Object(), "测试手动发布事件"));
    }
}

手动触发publishEvent,监听器依然会监听到。