Spring框架的事件机制允许对象在特定的事件发生时进行监听和响应。Spring监听器的原理主要涉及以下几个核心概念:
Spring监听器的工作流程如下:
Spring监听器的原理就是通过事件、事件源、事件监听器和事件发布器之间的协作来实现对应用程序中事件的监听和响应。这种机制使得应用程序能够更加灵活地处理各种动态变化,提高了系统的可扩展性和可维护性。
事件:类图
事件类名 | 作用 | 备注 |
---|---|---|
ContextRefreshedEvent | 事件被发布当ApplicationContext被初始化或者刷新时,它可以由refresh()方法引起在ConfigurableApplicationtext接口中。 | |
ContextStartedEvent | 事件被发布当ApplicationContext通过ConfiugrableApplication()接口的start()方法启动时。你可以查询数据库或者你可以重新启动任何停止的应用在收到这个事件后。 | |
ContextStoppedEvent | 事件被发布当ApplicationContext通过ConfigurableApplication接口的stop()方法停止时。你可以做必须的看家工作在收到这个事件时。 | |
ContextClosedEvent | 事件被发布当ApplicationContext通过ConfigurableApplicationContext接口的close()方法关闭时。一个关闭的上下文到达它声明的终点,不能在被刷新或者重启。 | |
RequestHandledEvent | 这是一个web专有的事件,告诉所有beans有一个HTTP请求已经被处理。 | 用于http请求及响应的监听器 |
几年前写过一个spring事件文章,可以参考:spring的事件
其实很容易可以看出来,该原理就是使用观察者模式来进行监听,这种好比,最近特大洪水事件:新闻联播(多播器)通告近日由于受台风影响,导致多省洪涝严重(事件),各地收到该信息(监听器)纷纷发起抢险救灾行动。
spring还有另外一种ApplicationEventMulticaster监听机制,它的作用是接收发布者发布的事件,并将事件传递给已注册的监听器进行处理。
与前面提到的RequestHandledEvent不同,ApplicationEventMulticaster是一个更通用的事件广播机制,用于在整个Spring应用程序中分发各种类型的事件。
ApplicationEventMulticaster的主要作用有以下几点:
ApplicationEventMulticaster是Spring框架中负责事件广播的机制,它能够接收发布者发布的事件,并将其传递给已注册的监听器进行处理。它与RequestHandledEvent不同,RequestHandledEvent是Spring提供的特定事件类,用于在处理HTTP请求后触发,而ApplicationEventMulticaster是一种通用的事件广播机制,用于整个Spring应用程序中分发各种类型的事件。
代码位置:org.springframework.context.support.AbstractApplicationContext#prepareRefresh
...
//创建初始化事件监听器
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
/** 初始化事件列表,自动将初始化事件监听器(自动添加不需要pubish)
*/
this.earlyApplicationEvents = new LinkedHashSet<>();
代码位置:org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
...
//注册后置处理器用来处理ApplicationContextAware接口的回调方法
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
...
代码位置:org.springframework.context.support.AbstractApplicationContext#refresh
...
// 注册事件多播器
initApplicationEventMulticaster();
...
//事件监听器注册到多播器上
registerListeners();
注意下面这个是手动去注册进去的
代码位置:org.springframework.context.support.AbstractApplicationContext#initApplicationEventMulticaster
/**事件多播器初始化 **/
protected void initApplicationEventMulticaster() {
//获取bean工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//如果没有多播器则应用多播器组件
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
//获取bean中的对象(提前初始化的)
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
//如果没有多播器
else {
//初始化简单的多播器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
//注入到容器中
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
代码位置:org.springframework.context.support.AbstractApplicationContext#registerListeners
/**初始化和懒加载都会调用注册 **/
protected void registerListeners() {
//获取所有监听器对象
for (ApplicationListener<?> listener : getApplicationListeners()) {
//把监听器注册到多播器上
getApplicationEventMulticaster().addApplicationListener(listener);
}
//获取自定的监听器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
//同样把自定义的监听器注册到多播器中
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
//获取初始化监听器
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
//将所有初始化的监听器置为空并进行广播(清空掉)
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
//通过多播器进行播发早期事件
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
发布事件监听器
代码位置:org.springframework.context.support.AbstractApplicationContext#finishRefresh
...
// 发布事件多播器
publishEvent(new ContextRefreshedEvent(this));
...
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
//发布初始化(早期)事件,唯一的地方
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
// 如果有上级则向上级也发布一份(传递依赖)
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
到这里初始化完毕所有监听器。
注意,spring默认的事件广播器为:org.springframework.context.event.SimpleApplicationEventMulticaster,如果不指定默认为它,且默认为同步。
通过方法multicastEvent实现监听
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
//获取所有监听器
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
//获取异常支持,有则是异常事件,否则是同步发
Executor executor = getTaskExecutor();
if (executor != null) {
//异步播发事件
executor.execute(() -> invokeListener(listener, event));
}
else {//同步发
invokeListener(listener, event);
}
}
}
很多中间件就是通过spring支持默认监听机制实现的,当然看具体实现方式和场景有兴趣的同学可以看看nacos、dubbo、mq等中都有集成的场景,在后续有机会再根据现在的基础进行学习。
参考文章:
https://www.cnblogs.com/shigongp/p/16685903.html
https://blog.csdn.net/biaolianlao0449/article/details/104246732/
https://blog.51cto.com/u_15346609/5646215