详解
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());
}
}
打印结果
事件说明
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,监听器依然会监听到。