一、什么是Event
ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。
二、Event
2.1、event的类型
2.2、context相关
序号 | 内置事件 | 解释 |
---|---|---|
1 | ContextRefreshedEvent | ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext 接口中使用 refresh() 方法来发生。 |
2 | ContextStartedEvent | 当使用 ConfigurableApplicationContext 接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序 |
3 | ContextStoppedEvent | 当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作 |
4 | ContextClosedEvent | 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启 |
2.3、Spring boot相关
序号 | 内置事件 | 解释 |
---|---|---|
1 | ApplicationStartingEvent | 在Spring最开始启动的时候触发 |
2 | ApplicationEnvironmentPreparedEvent | 在Spring已经准备好环境但是上下文尚未创建的时候触发 |
3 | ApplicationContextInitializedEvent | 在spring 创建和初始化好上下文,在 bean 的定义(bean definitions)被加载之前发送 |
4 | ApplicationPreparedEvent | 这个事件是在 Spring 上下文(context)刷新之前,且在 bean 的定义(bean definitions)被加载之后发送。 |
5 | ApplicationStartedEvent | 这个事件是在 Spring 上下文(context)刷新之后,且在 application/ command-line runners 被调用之前发送。 |
6 | ApplicationReadyEvent | 这个事件在任何 application/ command-line runners 调用之后发送 |
7 | ApplicationFailedEvent | 这个事件在应用启动异常时进行发送。 |
三、EventListener
3.1、新建监听器
ApplicationListener
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
public class BootDataSourceAutoConfiguration
implements ApplicationListener<ApplicationEnvironmentPreparedEvent>
{
private static DateTimeFormatter staticLocalDateTimeFormat;
private static DateTimeFormatter staticLocalTimeFormat;
public void onApplicationEvent(@NonNull ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment configurableEnvironment = event.getEnvironment();
if (null == staticLocalDateTimeFormat) {
String localDateTimeFormat = configurableEnvironment.resolvePlaceholders("${c2f.application.datasource.local-date-time.format:yyyy-MM-dd HH:mm:ss}");
staticLocalDateTimeFormat = DateTimeFormatter.ofPattern(localDateTimeFormat);
}
if (null == staticLocalTimeFormat) {
String localTimeFormat = configurableEnvironment.resolvePlaceholders("${c2f.application.datasource.local-time.format:HH:mm:ss}");
staticLocalTimeFormat = DateTimeFormatter.ofPattern(localTimeFormat);
}
}
}
使用@EventListener
public class MsgEvent extends ApplicationEvent {
private String msg;
public MsgEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
@Override
public String toString() {
return "MsgEvent{" +
"msg='" + msg + '\'' +
'}';
}
}
@EventListener(MsgEvent.class)
public void consumer(MsgEvent msgEvent) {
System.out.println("receive msg event by @anno: " + msgEvent);
}
3.2、EventListener注册
1、在资源目录中的 META-INF/spring.factories 文件中自动注册:
org.springframework.context.ApplicationListener=\ cn.javastack.springboot.features.listener.JavastackListener
2、如果是监听 Spring 应用上下文(ApplicationContext)创建之后的事件,可以直接在监听器上使用 @Component 注解即可,否则需要使用第一种方法的自动注册,因为 ApplicationContext 并未创建,这时的 Bean 是不能被加载的。
四、ApplicationEventMulticaster管理
用来向ApplicationListener广播消息
/**
* 添加监听器,用来接收所有事件的通知
*/
void addApplicationListener(ApplicationListener<?> listener);
/**
* 根据Bean名称添加监听器
*/
void addApplicationListenerBean(String listenerBeanName);
/**
* 移除监听器
*/
void removeApplicationListener(ApplicationListener<?> listener);
/**
* 根据名称移除监听器
*/
void removeApplicationListenerBean(String listenerBeanName);
/**
* 移除所有监听器
*/
void removeAllListeners();
/**
* 将事件广播到对应的监听器中
*/
void multicastEvent(ApplicationEvent event);
/**
* 将事件广播到对应的监听器中
*/
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);