在spring-context 5.3.26中来看一下它的定义:
package org.springframework.context;import java.util.EventListener;
import java.util.function.Consumer;@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {void onApplicationEvent(E event);static <T> ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer) {return (event) -> {consumer.accept(event.getPayload());};}
}
监听器顾名思义,它得监听点什么,就像老奶奶一样支楞着耳朵打听一些事情一样,它也要监听一些事件,它既然是在context包下,那么它也肯定和context有关。
它定义了一个泛型E事件,这个事件是ApplicationEvent类型,事件怎样通知给监听器呢?通过调用它的方法onApplicationEvent(E event);将这个事件给传进来。
当然了它还用一个forPayload方法,这个PayloadApplicationEvent其实也是继承ApplicationEvent,这个后讲。
那么ApplicationListener什么时候被回调呢?
事件发布:(例如自媒体发布的一篇油炸指甲盖能治疗脑血栓的文章,被栓柱娘刷抖音看到了)它的被回调时机是当应用程序中的某个部分(如一个Bean或者框架内部)需要通知其他组件某个事情发生时,它会创建一个事件对象(通常是ApplicationEvent
的子类),并通过调用ApplicationContext
的publishEvent(ApplicationEvent event)
方法来发布这个事件。
事件多播:(
栓柱娘看到了这个新闻发到自己的健康每一天姐妹群里)ApplicationContext
接收到事件后,它会使用内部的ApplicationEventMulticaster
来广播这个事件(前提是监听器都注册上来了,也就是类似于关注健康的老太太都在群里)。ApplicationEventMulticaster
维护了一个注册了的监听器列表,这些监听器都是实现了ApplicationListener
接口的Bean。
匹配与回调:(有脑血栓的老太太看到了,感到有趣就点开看了这篇文章)ApplicationEventMulticaster
会遍历这个列表,对于每个监听器,它会检查该监听器是否对该类型的事件感兴趣(即监听器泛型参数是否与发布的事件类型匹配)。如果匹配,它就会调用该监听器的onApplicationEvent(ApplicationEvent event)
方法,将事件传递给监听器,从而执行监听器中定义的业务逻辑。
我们再来看事件发布中的ApplicationContext ,它可不得了,它是IOC容器的高级模式,它是BeanFactory的拓展,他能管理Bean的生命周期,它能提供多种配置载入方式如(XML,注解等),它能自动装配Bean之间的依赖关系,它内置AOP支持,当然它也支持我们所讲的事件监听机制。
package org.springframework.context;import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.lang.Nullable;public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {@NullableString getId();String getApplicationName();String getDisplayName();long getStartupDate();@NullableApplicationContext getParent();AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
你看,它继承了ApplicationEventPublisher接口,说明它确实有发布事件的能力,也就是说这个高级容器能发布事件。
package org.springframework.context;@FunctionalInterface
public interface ApplicationEventPublisher {default void publishEvent(ApplicationEvent event) {this.publishEvent((Object)event);}void publishEvent(Object event);
}
spring还贴心的给我们整了几个事件,如ContextRefreshedEvent
、ContextStartedEvent
、ContextStoppedEvent
和ContextClosedEvent
,这些事件分别对应Spring容器的生命周期的不同阶段,监听这些事件可以让Bean在容器启动、刷新、停止、关闭时执行特定的操作。
我们再来看事件多播中的ApplicationEventMulticaster,Spring框架默认使用的ApplicationEventMulticaster
实现类是SimpleApplicationEventMulticaster
。这个类是ApplicationEventMulticaster
接口的一个基础且常用的实现,它维护了一个监听器列表,并在接收到事件时,按照顺序同步地调用这些监听器的onApplicationEvent
方法来广播事件。
SimpleApplicationEventMulticaster
注册监听器主要发生在Spring应用上下文初始化的过程中。具体来说,这个过程涉及以下几个步骤:
-
Bean的初始化:当Spring容器初始化Bean时,如果某个Bean实现了
ApplicationListener
接口,或者通过@EventListener
注解标记了处理事件的方法,那么这个Bean或方法就会被识别为事件监听器,并准备注册。 -
ApplicationContext初始化:在
ApplicationContext
初始化的后期,特别是调用refresh()
方法期间,会执行一系列的初始化工作,包括注册内部和用户定义的事件监听器。这是通过调用finishBeanFactoryInitialization(beanFactory)
方法完成的,该方法会初始化剩下的单例Beans,包括事件监听器。 -
显式注册:在某些情况下,开发人员可能通过编程方式直接向
ApplicationContext
或ApplicationEventMulticaster
实例注册监听器,这通常发生在应用的配置类中。 -
自动检测和注册:Spring在初始化过程中会自动检测并注册实现了
ApplicationListener
接口的Bean,或者使用了@EventListener
注解的方法作为监听器。
也就是说SimpleApplicationEventMulticaster
注册监听器主要是在Spring容器启动和初始化其Bean的时候。一旦容器完全初始化,所有监听器就已经注册完毕并准备好接收事件广播。
我们再看匹配与回调,我们看一下简单的例子:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;@Configuration
public class AppConfig {@Beanpublic CustomEventListener customEventListener() {return new CustomEventListener();}@Beanpublic ApplicationEventMulticaster applicationEventMulticaster(AbstractApplicationContext applicationContext) {SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();eventMulticaster.setTaskExecutor(null); // 可以自定义任务执行器以支持异步事件处理applicationContext.addApplicationListener(customEventListener());return eventMulticaster;}// 假设有一个服务类,用于在业务逻辑中触发事件@Beanpublic MyService myService(ApplicationEventMulticaster eventMulticaster) {return new MyServiceImpl(eventMulticaster);}
}class MyServiceImpl implements MyService {private final ApplicationEventMulticaster eventMulticaster;public MyServiceImpl(ApplicationEventMulticaster eventMulticaster) {this.eventMulticaster = eventMulticaster;}public void doSomething() {CustomEvent event = new CustomEvent(this, "Hello from Custom Event!");eventMulticaster.multicastEvent(event);}
}interface MyService {void doSomething();
}
最终它在eventMulticaster.multicastEvent(event);这里发布事件,在SimpleApplicationEventMulticaster类(这货就是ApplicationEventMulticaster的实现类,也是spring默认的事件广播器)的内部最终调用listener.onApplicationEvent(event);被listener监听到。
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);Executor executor = this.getTaskExecutor();Iterator var5 = this.getApplicationListeners(event, type).iterator();while(var5.hasNext()) {ApplicationListener<?> listener = (ApplicationListener)var5.next();if (executor != null) {executor.execute(() -> {this.invokeListener(listener, event);});} else {this.invokeListener(listener, event);}}}private ResolvableType resolveDefaultEventType(ApplicationEvent event) {return ResolvableType.forInstance(event);}protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {ErrorHandler errorHandler = this.getErrorHandler();if (errorHandler != null) {try {this.doInvokeListener(listener, event);} catch (Throwable var5) {errorHandler.handleError(var5);}} else {this.doInvokeListener(listener, event);}}private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {listener.onApplicationEvent(event);} catch (ClassCastException var6) {String msg = var6.getMessage();if (msg != null && !this.matchesClassCastMessage(msg, event.getClass()) && (!(event instanceof PayloadApplicationEvent) || !this.matchesClassCastMessage(msg, ((PayloadApplicationEvent)event).getPayload().getClass()))) {throw var6;}Log loggerToUse = this.lazyLogger;if (loggerToUse == null) {loggerToUse = LogFactory.getLog(this.getClass());this.lazyLogger = loggerToUse;}if (loggerToUse.isTraceEnabled()) {loggerToUse.trace("Non-matching event type for listener: " + listener, var6);}}}
这样就串起来了,你可以用spring自带的监听器,监听一些spring的事件,在spring要干嘛的时候你打听到这些事决定是否参与,你也可以自定义监听器监听约定好的事件,听起来像AOP似的,但是它是以事件为驱动的并不依赖AOP,可以根据自己的使用场景再决定是否用它。