起因
spring的监听器在spring容器整个生命流程中起着至关重要的作用,用了springboot以后更是如此,故有了此篇文章。
主要内容
文章分为三部分:
1.spring中简单使用demo演示。
2.监听器源码简单解析。
3.spring自己对于监听器的使用以及我们自己的使用
spring中简单使用demo演示
spring事件
spring监听器
正常版
简易版
wenku.baidu.com/view/32e85d… 详细解释
发布事件
监听器源码简单解析
大致流程
发布事件后,获取多播器广播事件,根据事件的类型获取对应的监听器,然后调用监听器的onApplicationEvent方法把对应事件传进去。
源码解析
入口 : applicationContext.publishEvent(new YaojieEvent("yaojie"));
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
//getApplicationListeners获取所有的对应事件的监听器 此处不分析getApplicationListeners方法
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
// executor不为null的话就异步执行
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
//调用监听器的onApplicationEvent方法也就是我们重写的方法
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
小总结
我们使用spring的监听器非常简单,其实spring自身的监听器实现也很简单,是对观察者模式的巧妙封装与实践,值得细细品味。
spring自己对于监听器的使用以及我们自己的使用
spring自己的简单使用
观察ApplicationEvent的继承结构,发现很多事件继承了它。
光观察这些类就知道spring容器各个阶段都在使用着监听器的相关功能。
spring中简单的例子
在spring容器结束刷新的方法中
我们自己的使用
我们也可以根据相关业务在spring容器相关阶段处理相关事件。 打个比方,我们登入时一般会把登入相关信息存入redis,但是项目关闭的时候应该清空redis登入相关信息, 就可以监听spring容器ContextStoppedEvent事件,在结束事件中进行相关操作(要调用spring容器相关方法优雅的关闭容器)。
也可以在spring容器启动的时候进行相关操作,一切以实际为准。
尾
本文对于spring监听器做了简单的分析与操作,如有错误请各位大佬指正!!!