前言

Spring事件一般用于应用程序状态变更的通知,也可用于单个服务内特定事件的通知场景。

在Spring中,提供了丰富的api来实现事件机制,一起看下其中包括的核心API。


核心API

事件ApplicationEvent):Spring事件的抽象基类,用于派生自定义事件,标识着某一类事件。
事件源EventSource):事件发生的源头,事件初始化时传递给事件的对象。
事件监听器ApplicationListener):订阅特定的事件,当事件产生时,监听该事件的监听器被触发通知。
事件发布器ApplicationEventPublisher):定义了发布事件的方法,实现类中,在适当时机发布特定事件。
事件广播器SimpleApplicationEventMulticaster):用于管理事件监听器和事件的广播,将事件传递给订阅该事件的监听器,作为事件发布器的代理。

事件 ApplicationEvent

// 所有自定义事件的基类,继承java事件api EventObject
public abstract class ApplicationEvent extends EventObject {

	/** use serialVersionUID from Spring 1.2 for interoperability. */
	private static final long serialVersionUID = 7099057708183571937L;

	/** System time when the event happened. */
	// 事件发生的系统时间
	private final long timestamp;


	/**
	 * Create a new {@code ApplicationEvent}.
	 * @param source the object on which the event initially occurred or with
	 * which the event is associated (never {@code null})
	 * source 不能为null
	 */
	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}


	/**
	 * Return the system time in milliseconds when the event occurred.
	 */
	public final long getTimestamp() {
		return this.timestamp;
	}

}

事件源 EventSource

在事件类ApplicationEvent中,构造器传递的source,便是事件源,会传递给EventObject的source成员变量。


事件监听器 ApplicationListener

// 范型要求继承于ApplicationEvent:<E extends ApplicationEvent>
// 继承java事件监听器api EventObject
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

事件发布器 ApplicationEventPublisher

@FunctionalInterface
public interface ApplicationEventPublisher {

    // 默认方法
	default void publishEvent(ApplicationEvent event) {
		publishEvent((Object) event);
	}

	// 如果事件不是继承ApplicationEvent,会被包装成PayloadApplicationEvent
	void publishEvent(Object event);

事件发布器接口,是个函数式接口,有一个默认方法,调用另一个抽象方法,抽象由子类实现,被AbstractApplicationContext实现,AbstractApplicationContext是应用上下文也是企业级容器的一个抽象类,是spring中一个关键的类。

继续看下发布事件的实现抽象类在做什么?

// org.springframework.context.support.AbstractApplicationContext

/**
 * Publish the given event to all listeners.
 * <p>Note: Listeners get initialized after the MessageSource, to be able
 * to access it within listener implementations. Thus, MessageSource
 * implementations cannot publish events.
 * @param event the event to publish (may be an {@link ApplicationEvent}
 * or a payload object to be turned into a {@link PayloadApplicationEvent})
 *  
 * 注意,此处有个说明:监听器注册是在MessageSource后,所以MessageSource实现中不建议发布事件。
 *
 *  此处还提到,event可能是一个ApplicationEvent实现类,也可能不是,如果不是,会包装成PayloadApplicationEvent事件
 */
@Override
public void publishEvent(Object event) {
        publishEvent(event, null);
}

/**
 * Publish the given event to all listeners.
 * @param event the event to publish (may be an {@link ApplicationEvent}
 * or a payload object to be turned into a {@link PayloadApplicationEvent})
 * @param eventType the resolved event type, if known
 * @since 4.2
 */
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
        Assert.notNull(event, "Event must not be null");

        // Decorate event as an ApplicationEvent if necessary
        // 如果属于ApplicationEvent则强转
        ApplicationEvent applicationEvent;
        if (event instanceof ApplicationEvent) {
                applicationEvent = (ApplicationEvent) event;
        }
        else {
                // 如果发布的不是ApplicationEvent,则包装一个PayloadApplicationEvent
                applicationEvent = new PayloadApplicationEvent<>(this, event);
                if (eventType == null) {
                        eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
                }
        }

        // Multicast right now if possible - or lazily once the multicaster is initialized
        // 如果可能的话,立马进行广播事件,否则延迟到multicaster初始化后。
        // 因为在 getApplicationEventMulticaster()
        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);
                }
        }
}

有个注意事项:
监听器注册是在MessageSource后,所以MessageSource实现中不建议发布事件。但是可以向ApplicationContext中增加监听器,等待事件广播器注册后,会立马进行发布。

其中有个getApplicationEventMulticaster()方法,一起看下:

// org.springframework.context.support.AbstractApplicationContext

ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
		if (this.applicationEventMulticaster == null) {
			throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
					"call 'refresh' before multicasting events via the context: " + this);
		}
		return this.applicationEventMulticaster;
	}

获取广播器,固定bean名称:APPLICATION_EVENT_MULTICASTER_BEAN_NAME = “applicationEventMulticaster”。
在AbstractApplicationContext#initApplicationEventMulticaster中被初始化。

所以事件的发布时通过事件广播器 ApplicationEventMulticaster进行发布的,继续看下事件广播器ApplicationEventMulticaster。


事件广播器

包括3个如下api:

ApplicationEventMulticaster:是个接口,用于管理事件监听器,同时负责将事件广播给监听了该事件的监听器。
AbstractApplicationEventMulticaster:抽象类,实现ApplicationEventMulticaster接口,提供了大部分核心逻辑。
SimpleApplicationEventMulticaster:唯一实现类,继承AbstractApplicationEventMulticaster类,同时支持Executor异步回调监听器(默认同步调用)与错误处理ErrorHandler(默认监听器异常进行抛出),api相对简单。

下面主要看下核心api AbstractApplicationEventMulticaster类的定义说明

// ApplicationEventMulticaster接口的抽象实现
public abstract class AbstractApplicationEventMulticaster
		implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {

	// 默认监听器的回收器,包括所有的。
	// 以此为锁,保障defaultRetriever中数据操作的线程安全
    // Helper class that encapsulates(封装) a general set of target listeners.
	private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();

	// 监听器缓存,key:事件类型和事件源Class;value:目标监听器集合
	// 在根据事件类型获取监听器时使用
    // Helper class that encapsulates a specific set of target listeners
	final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);
   	
   	@Override
	public void addApplicationListener(ApplicationListener<?> listener) {
        synchronized (this.defaultRetriever) {
                // Explicitly remove target for a proxy, if registered already,
                // in order to avoid double invocations of the same listener.
                // 去除代理的事件监听器,防止重复回调。这里代理类,是单例类在aop的场景下经过SingletonTargetSource包装的类
                Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
                if (singletonTarget instanceof ApplicationListener) {
                        this.defaultRetriever.applicationListeners.remove(singletonTarget);
                }
                this.defaultRetriever.applicationListeners.add(listener);
                this.retrieverCache.clear();
        }
}

// ... 省略了些添加和移除监听器的实现方法,及获取全量监听器的方法

/**
 * 获取指定事件类型的监听器集合
 *
 * @param eventType the event type
 * @return a Collection of ApplicationListeners
 */
protected Collection<ApplicationListener<?>> getApplicationListeners(
                ApplicationEvent event, ResolvableType eventType) {
        // 事件源
        Object source = event.getSource();
        // 事件源类Class对象
        Class<?> sourceType = (source != null ? source.getClass() : null);
        // 监听器缓存key,按事件类型和事件源类型
        ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

        // Potential new retriever to populate
        CachedListenerRetriever newRetriever = null;

        // 从缓存中去
        CachedListenerRetriever existingRetriever = this.retrieverCache.get(cacheKey);
        if (existingRetriever == null) {
                // Caching a new ListenerRetriever if possible
                if (this.beanClassLoader == null ||
                                (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
                                                (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
                        newRetriever = new CachedListenerRetriever();
                        existingRetriever = this.retrieverCache.putIfAbsent(cacheKey, newRetriever);
                        if (existingRetriever != null) {
                                newRetriever = null;  // no need to populate it in retrieveApplicationListeners
                        }
                }
        }

        // 缓存中有,返回特定事件和事件源类型的监听器集合
        if (existingRetriever != null) {
                Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();
                if (result != null) {
                        return result;
                }
        }

        // 匹配事件监听器
        return retrieveApplicationListeners(eventType, sourceType, newRetriever);
}


/**
 * 解析对应事件和源类型的监听器,记录事件与监听器的对应关系并存入缓存中
* 支持事件监听器类和监听器bean名称查询
 *
 * @return the pre-filtered list of application listeners for the given event and source type
 */
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
                ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable CachedListenerRetriever retriever) {

        List<ApplicationListener<?>> allListeners = new ArrayList<>();

        // retriever不为null时,才会处理filteredListeners和filteredListenerBeans字段。处理完赋值进去。
        Set<ApplicationListener<?>> filteredListeners = (retriever != null ? new LinkedHashSet<>() : null);

        // 存在bean名称,且不是单例
        Set<String> filteredListenerBeans = (retriever != null ? new LinkedHashSet<>() : null);

        Set<ApplicationListener<?>> listeners;
        Set<String> listenerBeans;
        synchronized (this.defaultRetriever) {
                listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
                listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
        }

        // Add programmatically registered listeners, including ones coming
        // from ApplicationListenerDetector (singleton beans and inner beans).
        for (ApplicationListener<?> listener : listeners) {
                if (supportsEvent(listener, eventType, sourceType)) {
                        if (retriever != null) {
                                filteredListeners.add(listener);
                        }
                        allListeners.add(listener);
                }
        }

        // Add listeners by bean name
        if (!listenerBeans.isEmpty()) {
                ConfigurableBeanFactory beanFactory = getBeanFactory();
                for (String listenerBeanName : listenerBeans) {
                        try {
                 		// beanFactory检查bean定义的监听器的泛型声明,是不是对应事件类型。
                                if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
                                        ApplicationListener<?> listener =
                                                        beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                                        if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
                                                if (retriever != null) {
                                                        if (beanFactory.isSingleton(listenerBeanName)) {
                                                                filteredListeners.add(listener);
                                                        }
                                                        else {
                                                                filteredListenerBeans.add(listenerBeanName);
                                                        }
                                                }
                                                allListeners.add(listener);
                                        }
                                }
                                else {
                                        Object listener = beanFactory.getSingleton(listenerBeanName);
                                        if (retriever != null) {
                                                filteredListeners.remove(listener);
                                        }
                                        // 移除掉不匹配的
                                        allListeners.remove(listener);
                                }
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                                // Singleton listener instance (without backing bean definition) disappeared -
                                // probably in the middle of the destruction phase
                        }
                }
        }

        AnnotationAwareOrderComparator.sort(allListeners);
        if (retriever != null) {
                if (filteredListenerBeans.isEmpty()) {
                        // 没有该情况:存在bean名称且不是单例的beanName,使用allListeners即可
                        // 如果存在bean名称的数据且是单例,会直接存储对应bean,上层调用时不用再转了。
                        retriever.applicationListeners = new LinkedHashSet<>(allListeners);
                        retriever.applicationListenerBeans = filteredListenerBeans;
                }
                else {
                        // 否则使用过滤的filteredListeners bean
                        retriever.applicationListeners = filteredListeners;
                        retriever.applicationListenerBeans = filteredListenerBeans;
                }
        }
        return allListeners;
}


/**
 * 检查bean定义的监听器的泛型声明,是不是对应事件类型。
 *
 * 还有其他的supportsEvent方法,主要用来判断监听器是否对应该事件。
 *
 * @return whether the given listener should be included in the candidates
 * for the given event type
 */
private boolean supportsEvent(
                ConfigurableBeanFactory beanFactory, String listenerBeanName, ResolvableType eventType) {

        Class<?> listenerType = beanFactory.getType(listenerBeanName);
        if (listenerType == null || GenericApplicationListener.class.isAssignableFrom(listenerType) ||
                        SmartApplicationListener.class.isAssignableFrom(listenerType)) {
                return true;
        }
        if (!supportsEvent(listenerType, eventType)) {
                return false;
        }
        try {
                BeanDefinition bd = beanFactory.getMergedBeanDefinition(listenerBeanName);
                ResolvableType genericEventType = bd.getResolvableType().as(ApplicationListener.class).getGeneric();
                return (genericEventType == ResolvableType.NONE || genericEventType.isAssignableFrom(eventType));
        }
        catch (NoSuchBeanDefinitionException ex) {
                // Ignore - no need to check resolvable type for manually registered singleton
                return true;
        }
}

api中多个方法增加了synchronized同步锁:
一方面,因为涉及两个缓冲,定义为共享变量,需要保证操作的原子性;另一方面,监听器缓存中存储的是线程不安全的集合类型,在操作时需要保证线程的安全。故而要增加synchronized同步锁机制。

还有个判断方法:

protected boolean supportsEvent(Class<?> listenerType, ResolvableType eventType) {
	ResolvableType declaredEventType = GenericApplicationListenerAdapter.resolveDeclaredEventType(listenerType);
	return (declaredEventType == null || declaredEventType.isAssignableFrom(eventType));
}

通过isAssignableFrom可知,只要监听器声明的事件是发布事件的父类,监听器都能收到,例如监听器监听ApplicationEvent,那么发布任何ApplicationEvent的子类,监听器均能收到消息。


总结

了解整个Spring事件的设计,包括一些实现的细节。能够注意到,对于监听器声明的事件,如果其声明事件是发布事件的父类,事件监听器便可以收到通知。
同时可以借鉴,Spring事件场景,一般事件的监听器定义在服务启动后比较固定,而发布事件可能随时发生,对于获取监听器来说,可以理解为读多写少的场景,考虑增加缓存,来提高执行效率。