SpringBoot版本:2.0.2.RELEASE
SpringFramework版本:5.0.6.RELEASE
实现泛型的机制
前了前面几篇文章的铺陈,这个话题就容易描述了,读者可顾回这几篇文章:
- 《SpringFramework事件与监听机制(发布器)》
- 《SpringFramework事件与监听机制(事件)》
- 《SpringFramework事件与监听机制(监听器)》
泛型事件的发布
AbstractApplicationContext作为ApplicationEventPublisher接口的实现类,它承担起事件发布任务。在重写的publishEvent方法的关键代码如下:
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
....
// 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();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null)
{
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
....
}
方法在发布事件前,先判断事件是否ApplicationEvent类型,如果不是就封装成PayloadApplicationEvent事件。
public class PayloadApplicationEvent<T> extends ApplicationEvent implements ResolvableTypeProvider {
private final T payload;
/**
* Create a new PayloadApplicationEvent.
* @param source the object on which the event initially occurred (never {@code null})
* @param payload the payload object (never {@code null})
*/
public PayloadApplicationEvent(Object source, T payload) {
super(source);
Assert.notNull(payload, "Payload must not be null");
this.payload = payload;
}
@Override
public ResolvableType getResolvableType() {
return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getPayload()));
}
/**
* Return the payload of the event.
*/
public T getPayload() {
return this.payload;
}
}
从类的定义上看,PayloadApplicationEvent继承于ApplicationEvent。PayloadApplicationEvent实现ResolvableTypeProvider接口,它定义的方法返回的ResolvableType是将PayloadApplicationEvent的类型以及以payload属性的具体类型作为的泛型揉合在一起的结合物作为事件的类型。它以PayloadApplicationEvent类型为原生类型,以payload属性的具体类型为泛型。在此我们可以想象一下,在类型定义层面,我们为类添加了泛型标记,这样子明确了类是带泛型的,泛型的具体类型是不清楚的,在真正使用到这类型的时候才会指定泛型的真正类型。而Spring Framework封装的ResolvableType在运行时可将两个不同的类型揉合到一起,作用在事件与监听机制的过虑中能起到甄别监听器的作用,这设计摆脱了类定义的固定模式,让类之间的结合变得灵活起来,真是高明。相信在Spring Framework其他方面也会起到类似的作用。
在AbstractApplicationContext#publishEvent方法体里可知,PayloadApplicationEvent以ConfigurableApplicationContext作为事件源,目前还不清楚这样处理的用意何在。
在《SpringFramework事件与监听机制(监听器)》里描述过,SimpleApplicationEventMulticaster在发布事件时,会调用父类的getApplicationListeners方法,该方法会返回与事件相匹配的Listener集合。那么如何甄别事件类型监听器是否匹配,就得看AbstractApplicationEventMulticaster#supportsEvent方法:
protected boolean supportsEvent(
ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType