该篇文章是我学习SpringEvent源码实现的过程,看源码的过程中,会涉及到程序启动时系统监听类的注入、自定义监听类的注入、事件发布后如何通知监听类等等,如果一一记录,就显得又长又混乱了,所以本篇只涉及事件发布后如何通知监听类的源码,其他的只会稍微提一提。
关于SpringEvent的介绍和应用可以看我之前写的文章
SpringEvent介绍与应用
我们使用SpringEvent的时候,是使用ApplicationEventPublisher
的publishEvent
方法进行发布事件的操作,看一下publishEvent
方法做了什么操作
PS: ApplicationEventPublisher是一个接口,而接口ApplicationContext实现了该接口,Springboot默认实现是AbstractApplicationContext,所以我们看的实际类是AbstractApplicationContext的publishEvent方法
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
Object applicationEvent;
//检查传过来的event是否是了ApplicationEvent的实例
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent)event;
} else {
//如果不是,则会使用ApplicationEvent的实例包裹住event类
applicationEvent = new PayloadApplicationEvent(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
}
}
//earlyApplicationEvents 该事件是早期应用的事件模式,现在用的是多播的方式,也就是else部分的代码
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
} else {
//获取默认实现的事件多播器,并调用多播的方法,SpringEvent的发布会走此方法
this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
}
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
}
上述的代码在我理解中,作用是用来检验发布的事件是否符合要求,并解析事件的类型,方便后续获取具体的监听类中
接下来我们需要关注的是
this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
this.getApplicationEventMulticaster() 获取实现了ApplicationEventMulticaster的实例,SpringBoot默认实现是SimpleApplicationEventMulticaster
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
//如果eventType是空,则重新获取event的类型
ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
//获取任务线程池,如果没有自定义赋值,那么executor默认都会为null。
Executor executor = this.getTaskExecutor();
//this.getApplicationListeners(event, type)是获取event的监听类,获取监听类后进行遍历
Iterator var5 = this.getApplicationListeners(event, type).iterator();
while(var5.hasNext()) {
//获取event的监听类
ApplicationListener> listener = (ApplicationListener)var5.next();
//检测executor是否为null,如果不为null,则使用executor的线程异步跑监听类
if (executor != null) {
executor.execute(() -> {
this.invokeListener(listener, event);
});
} else {
this.invokeListener(listener, event);
}
}
}
该方法主要是获取事件对应的全部监听类,并进行调用
下面我们看是如何获取到事件的监听类。
protected Collection> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class> sourceType = source != null ? source.getClass() : null;
//下面三行代码是为了从缓存中获取对应的监听类
AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType);
AbstractApplicationEventMulticaster.CachedListenerRetriever newRetriever = null;
AbstractApplicationEventMulticaster.CachedListenerRetriever existingRetriever = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.get(cacheKey);
//如果缓存不存在,则对newRetriever和existingRetriever进行初步处理
if (existingRetriever == null &&
(this.beanClassLoader == null ||
ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))))
{
newRetriever = new AbstractApplicationEventMulticaster.CachedListenerRetriever();
111 = (AbstractApplicationEventMulticaster.CachedListenerRetriever)this.retrieverCache.putIfAbsent(cacheKey, newRetriever);
if (existingRetriever != null) {
newRetriever = null;
}
}
//如果缓存存在对应的监听类,则返回。
if (existingRetriever != null) {
Collection> result = existingRetriever.getApplicationListeners();
if (result != null) {
return result;
}
}
//获取对应的监听类(当缓存获取不到监听类就会走这一步)
return this.retrieveApplicationListeners(eventType, sourceType, newRetriever);
}
该方法的主要目的是为了先从缓存获取监听类,如果获取不到对应的监听类,再进行实时获取
该方法比较长,这里分成几个部分进行说明
说明:retrieveApplicationListeners方法的第三个参数retriever是用来做缓存listener用的
private Collection> retrieveApplicationListeners(ResolvableType eventType,
@Nullable Class> sourceType,
@Nullable AbstractApplicationEventMulticaster.CachedListenerRetriever retriever)
{
//用来作为结果返回的集合
List> allListeners = new ArrayList();
//filteredListeners和filteredListenerBeans的作用是用来做缓存数据的
//所以这里会识别retriever是否为null,如果不为null则新创集合
Set> filteredListeners = retriever != null ? new LinkedHashSet() : null;
Set filteredListenerBeans = retriever != null ? new LinkedHashSet() : null;
//存储监控类
LinkedHashSet listeners;
//存储String类型的Bean名称
LinkedHashSet listenerBeans;
synchronized(this.defaultRetriever) {
//将全部监控类放入listeners
listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
//将自定义的监控类放入listenerBeans(我们自己定义的监听类就在里面)
listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
}
}
this.defaultRetriever.applicationListeners
this.defaultRetriever.applicationListenerBeans
private Collection> retrieveApplicationListeners(ResolvableType eventType,
@Nullable Class> sourceType,
@Nullable AbstractApplicationEventMulticaster.CachedListenerRetriever retriever)
{
//准备部分
//第一部分
Iterator var9 = listeners.iterator();
while(var9.hasNext()) {
//取出listeners中的元素
ApplicationListener> listener = (ApplicationListener)var9.next();
//this.supportsEvent是用来筛选的,判断是不是符合事件的监听类
if (this.supportsEvent(listener, eventType, sourceType)) {
//如果缓存参数retriever存在,则往缓存集合存入数据
if (retriever != null) {
filteredListeners.add(listener);
}
//加入到结果集中
allListeners.add(listener);
}
}
}
第一部分的作用在于筛选对应的监控类,并把这些监控类也放进缓存集合中
private Collection> retrieveApplicationListeners(ResolvableType eventType,
@Nullable Class> sourceType,
@Nullable AbstractApplicationEventMulticaster.CachedListenerRetriever retriever)
{
//准备部分
//第一部分
//第二部分
if (!listenerBeans.isEmpty()) {
ConfigurableBeanFactory beanFactory = this.getBeanFactory();
Iterator var16 = listenerBeans.iterator();
while(var16.hasNext()) {
//获取bean名称
String listenerBeanName = (String)var16.next();
try {
//筛选是否是事件对应的监听类
if (this.supportsEvent(beanFactory, listenerBeanName, eventType)) {
//根据beanFactory取到bean
ApplicationListener> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class);
//如果结果集合allListeners中不存在该监听类并且是事件对应的监听类
//则往结果集和缓存集合中插入
if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) {
//判断缓存是否存在
if (retriever != null) {
if (beanFactory.isSingleton(listenerBeanName)) {
filteredListeners.add(listener);
} else {
filteredListenerBeans.add(listenerBeanName);
}
}
//往结果集中加入
allListeners.add(listener);
}
}
//这里进入else代码表示,集合元素并不是事件对应的监听器
else {
Object listener = beanFactory.getSingleton(listenerBeanName);
//对缓存进行处理
if (retriever != null) {
filteredListeners.remove(listener);
}
//
allListeners.remove(listener);
}
} catch (NoSuchBeanDefinitionException var13) {
}
}
}
}
第二部分大致分两个做法。
这部分虽说我知道是做什么的,但是我不知道为什么要这么做,如果有知道的大佬,希望能通过评论区告诉我下
private Collection> retrieveApplicationListeners(ResolvableType eventType,
@Nullable Class> sourceType,
@Nullable AbstractApplicationEventMulticaster.CachedListenerRetriever retriever)
{
//准备部分
//第一部分
//第二部分
//第三部分
//对结果集监听类进行排序
AnnotationAwareOrderComparator.sort(allListeners);
//如果缓存retriever不为空,则进行处理
if (retriever != null) {
//如果filteredListenerBeans集合不为空,
if (filteredListenerBeans.isEmpty()) {
retriever.applicationListeners = new LinkedHashSet(allListeners);
retriever.applicationListenerBeans = filteredListenerBeans;
}
else {
retriever.applicationListeners = filteredListeners;
retriever.applicationListenerBeans = filteredListenerBeans;
}
}
}
第三个部分比较简单,即对监听类进行排序和缓存的一些处理
SpringEvent的源码已大致描述完毕,谢谢看官愿意看到这里(源码的文章个人觉得很难描述的一下就明白了),如果有什么误人子弟的内容存在,可以在评论区回复。