文章目录
通过ApplicationContextAware我们可以把系统中所有ApplicationEvent传播给系统中所有的ApplicationListener。因此,我们只需要构造好我们自己的ApplicationEvent和ApplicationListener,就可以在系统中实现相应的监听器。
如果在上下文中部署一个实现了ApplicationListener接口的bean,那么每当在一个ApplicationEvent发布到 ApplicationContext时,这个bean得到通知。其实这就是标准的Oberver设计模式。
ApplicationListener
是一个接口,里面只有一个onApplicationEvent方法。具体的执行逻辑
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
SmartApplicationListener 接口继承了ApplicationListener,并继承了Order接口
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
}
ApplicationEvent
是个抽象类,里面只有一个构造函数和一个长整型的timestamp。实现类可以扩充相应的属性。
使用
继承ApplicationListener
public class DemoApplicationListener implements ApplicationListener<ContextRefreshedEvent>{
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
System.out.println("DemoApplicationListener 被调用了。");
}
}
通过配置类进行实例化
@Configuration
public class ListenerConfig {
@Bean
public ApplicationStartListener applicationStartListener(){
return new ApplicationStartListener();
}
}
自定义ApplicationListener
实现步骤
- 自定义事件:扩展ApplicationEvent类,需要有构造函数。
- 自定义事件监听器:实现ApplicationListener接口,重写onApplicationEvent方法,该方法处理监听到某个时间后做哪些操作。
- 通过ApplicationContext发布事件
Spring 提供的ApplicationEvent & Listener有3种实现方式:
- @EventListener 注解的方式;
- 实现ApplicationListener接口;
- 实现SmartApplicationListener接口;
@EventListener
通过给方法添加@EventListener注解实现
@Component
public class MyApplicationListener {
//参数的范围越广泛,监听到的事件越多
//如果入参是ApplicationEvent,则每当容器内发生任何事件时,此方法都会被触发
//如果入参是MyApplicationEvent,则只有容器内发生如果入参是MyApplicationEvent事件时,此方法才会被触发
@EventListener
public void onApplicationEvent(ApplicationEvent event) {
System.out.println(event.getClass().getName() + "被监听......");
if(event instanceof MyApplicationEvent){
MyApplicationEvent myApplicationEvent = (MyApplicationEvent) event;
System.out.println("MyApplicationEvent.msg is :"+(myApplicationEvent.getMsg()));
}
}
}
SmartApplicationListener
SmartApplicationListener是高级监听器,是ApplicationListener的子类,能够实现有序监听。
SmartApplicationListener接口继承了ApplicationListener 和 Ordered接口,实现了事件监听和排序的功能。
@Component
public class OrderEventListener implements SmartApplicationListener {
/**
* 支持的事件类型
*
* @param eventType
* @return
*/
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return eventType == OrderStatusMsgEvent.class;
}
/**
* 事件发生的目标类
*
* @param sourceType 事件发生的目标类类型
* @return
*/
@Override
public boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
@Override
public int getOrder() {
return 0;
}
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
// 获取注册用户信息
OrderStatusMsgEvent orderStatusMsgEvent = (OrderStatusMsgEvent) applicationEvent;
OrderDTO orderInfo = orderStatusMsgEvent.getOrderDTO();
// 模拟kafka发送
// kafkaProducer.sendMsg(orderInfo);
System.out.println("======kafka发送成功====");
}
}
支持异步
onApplicationEvent上增加 @Async 即可
@Override
@Async
public void onApplicationEvent(ApplicationEvent applicationEvent)
自定义ApplicationEvent
上例中的ContextRefreshedEvent会在Spring容器初始化完成会触发该事件。我们也可以自定义ApplicationEvent。
public class DemoApplicationEvent extends ApplicationEvent{
//设置一系列的属性
}
触发自定义的ApplicationEvent
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
DemoApplicationEvent event = new DemoApplicationEvent ();
//主动触发该事件
context.publishEvent(event);
内置的ApplicationEvent
内置事件 | 描述 |
---|---|
ContextRefreshedEvent | pplicationContext 被初始化或刷新时,该事件被发布。 |
ContextStartedEvent | 当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。 |
ContextStoppedEvent | 当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。 |
ContextClosedEvent | 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。 |
RequestHandledEvent | 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。 |
内置的ApplicationListener
在 SpringApplication 构造方法中,会调用 #getSpringFactoriesInstances(Class type) 方法,获得 ApplicationListener 集合。这个利用的还是Factories机制。spring.factories文件的定义如下
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
ConfigFileApplicationListener实现 SmartApplicationListener、Ordered、EnvironmentPostProcessor 接口,实现 Spring Boot 配置文件的加载。
AnsiOutputApplicationListener 现 ApplicationListener、Ordered 接口,在 Spring Boot 环境变量(environment)准备完成以后运行。
GenericApplicationListener 实现根据配置初始化日志系统 Logger 。
ClasspathLoggingApplicationListener ,实现 GenericApplicationListener 接口,程序启动时,将 classpath 打印到 debug 日志,启动失败时 classpath 打印到 debug 日志。