spring--11--基于XML的事件监听原理

spring–基于XML的事件监听原理

文章目录

1 概念

观察者模式的典型代表就是监听器,那么spring是如何使用它的呢?

2 spring提供的标准事件

在这里插入图片描述

事件说明
ContextRefreshedEventApplicationContext初始化或刷新完成时发布(finishRefresh()中发布该事件)
ContextStartedEventApplicationContext调用生命周期接口的start()方法发布该事件。通常,此start()方法用于在显式停止后重新启动组件,但也可以用于启动尚未配置为自动启动的组件(例如,尚未在初始化时启动的组件)。
ContextStoppedEventApplicationContext调用生命周期接口的stop()方法发布该事件。此处,“Stopped”表示所有Lifecycle bean均收到明确的停止信号。停止的上下文可以通过start()方法调用重新启动 。
ContextClosedEventApplicationContext调用生命周期接口的close()方法发布该事件,在这里,“Closed”意味着所有单例bean都将被销毁。关闭上下文后,它将达到使用寿命,无法刷新或重新启动
RequestHandledEvent一个特定于Web的事件,告诉所有BeanHTTP请求已得到服务。请求完成后,将发布此事件。此事件仅适用于使用SpringWeb应用程序DispatcherServlet
ServletRequestHandledEventRequestHandledEvent类的子类,添加了特定于Servlet的上下文信息。

2.1 自定义事件

我们可以创建和发布自己的自定义事件,只需要实现ApplicationEvent接口即可。

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})
     */
    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;
    }

}
  • ApplicationEvent中定义了一个时间戳,记录当前事件的产生时间
  • 只有一个默认的有参构造方法,创建事件的时候,必须把事件要操作的对象设置进去

下面是我们自定义的BlockedListEvent事件

public class BlockedListEvent extends ApplicationEvent {

    //事件携带的信息
    private final String address;
    private final String content;

    public BlockedListEvent(Object source, String address, String content) {
        super(source);
        this.address = address;
        this.content = content;
    }

    // accessor and other methods...
}

2.2 发布事件

要想发布一个事件,我们就必须得到事件多播器,spring提供了一个接口ApplicationEventPublisherAware,用户只需要实现这个接口,spring就会在创建对象的时候自动调用接口的setApplicationEventPublisher方法,将应用事件发布器注入进去。

public class EmailService implements ApplicationEventPublisherAware {

    private List<String> blockedList;
    private ApplicationEventPublisher publisher;

    public void setBlockedList(List<String> blockedList) {
        this.blockedList = blockedList;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void sendEmail(String address, String content) {
        if (blockedList.contains(address)) {
            /**
             * BlockedListEvent是用户自定义的事件,只需要实现ApplicationEvent接口即可
             * 调用publishEvent方法发布一个BlockedListEvent事件
             */
            publisher.publishEvent(new BlockedListEvent(this, address, content));
            return;
        }
        // send email...
    }
}

3 事件多播器ApplicationEventMulticaster

3.1 spring启动过程中自动创建事件多播器

/**
 * Initialize the ApplicationEventMulticaster.
 * Uses SimpleApplicationEventMulticaster if none defined in the context.
 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
 */
protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    /**
     * 用户可以自定义一个名字为applicationEventMulticaster的事件多播器,
     * 在容器启动过程中,会为上下文自动实例化这个多播器
     * 5.2中发布事件的时候会使用上下文的这个事件多播器发布事件
     */
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    //使用容器默认的事件多播器
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                         "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
        }
    }
}

3.2 默认的事件多播器SimpleApplicationEventMulticaster

下面是它的UML

在这里插入图片描述

从图上可以看到,它实现了两个Aware接口,也就是说它在被spring创建的时候可以自动向对象中注入BeanFactory对象和ClassLoader对象。那接下来我们再看看ApplicationEventMulticaster接口有哪些方法,它能做什么?

在这里插入图片描述

总结:

  • addApplicationListener方法和addApplicationListenerBean方法:向多播器中注册监听器
  • removeApplicationListener方法、removeApplicationListenerBean方法和removeAllListeners方法:移除监听器
  • multicastEvent方法:发布事件

3.3 AbstractApplicationEventMulticaster的几个内部类的作用

spring事件多播器实现并不简单,因为多播器内部就已经进行了事件和监听器的匹配。只要用户监听器实现

ApplicationListener接口的时候指定泛型,也就是监听事件的类型,spring就会自动将该事件推送给泛型匹配的监听器,而不会推送给别的监听器。

下面是该类的两个重要属性:

//所有的监听器都保存在这里面
private final DefaultListenerRetriever defaultRetriever = new DefaultListenerRetriever();

/**
 * 缓存
 * key为封装的事件类型
 * value为能够监听该事件类型的所有监听器
 */
final Map<ListenerCacheKey, CachedListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);

下面我们就来看一下它所涉及到的三个内部类

3.3.1 ListenerCacheKey(封装的事件类型)

/**
 * Cache key for ListenerRetrievers, based on event type and source type.
 */
private static final class ListenerCacheKey implements Comparable<ListenerCacheKey> {

    //事件的ResolvableType类型
    private final ResolvableType eventType;

    //事件源对象的类型,见6.3
    @Nullable
    private final Class<?> sourceType;

    public ListenerCacheKey(ResolvableType eventType, @Nullable Class<?> sourceType) {
        Assert.notNull(eventType, "Event type must not be null");
        this.eventType = eventType;
        this.sourceType = sourceType;
    }

    @Override
    public boolean equals(@Nullable Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof ListenerCacheKey)) {
            return false;
        }
        ListenerCacheKey otherKey = (ListenerCacheKey) other;
        return (this.eventType.equals(otherKey.eventType) &&
                ObjectUtils.nullSafeEquals(this.sourceType, otherKey.sourceType));
    }

    @Override
    public int hashCode() {
        return this.eventType.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.sourceType);
    }

    @Override
    public String toString() {
        return "ListenerCacheKey [eventType = " + this.eventType + ", sourceType = " + this.sourceType + "]";
    }

    //排序策略
    @Override
    public int compareTo(ListenerCacheKey other) {
        int result = this.eventType.toString().compareTo(other.eventType.toString());
        if (result == 0) {
            if (this.sourceType == null) {
                return (other.sourceType == null ? 0 : -1);
            }
            if (other.sourceType == null) {
                return 1;
            }
            result = this.sourceType.getName().compareTo(other.sourceType.getName());
        }
        return result;
    }
}

总结:

  • 实现了Comparable接口,那么就能对retrieverCache这个Map集合进行排序了
  • 该类封装了事件源对象的类型和事件类型,也就是说spring是根据这两种类型来确定监听器

3.3.2 CachedListenerRetriever(事件多播器缓存某种事件对应的监听器的地方)

/**
 * Helper class that encapsulates a specific set of target listeners,
 * allowing for efficient retrieval of pre-filtered listeners.
 * <p>An instance of this helper gets cached per event type and source type.
 */
private class CachedListenerRetriever {

    @Nullable
    public volatile Set<ApplicationListener<?>> applicationListeners;

    @Nullable
    public volatile Set<String> applicationListenerBeans;

    @Nullable
    public Collection<ApplicationListener<?>> getApplicationListeners() {
        Set<ApplicationListener<?>> applicationListeners = this.applicationListeners;
        Set<String> applicationListenerBeans = this.applicationListenerBeans;
        if (applicationListeners == null || applicationListenerBeans == null) {
            // Not fully populated yet
            return null;
        }

        List<ApplicationListener<?>> allListeners = new ArrayList<>(
            applicationListeners.size() + applicationListenerBeans.size());
        allListeners.addAll(applicationListeners);
        if (!applicationListenerBeans.isEmpty()) {
            BeanFactory beanFactory = getBeanFactory();
            for (String listenerBeanName : applicationListenerBeans) {
                try {
                    allListeners.add(beanFactory.getBean(listenerBeanName, ApplicationListener.class));
                }
                catch (NoSuchBeanDefinitionException ex) {
                    // Singleton listener instance (without backing bean definition) disappeared -
                    // probably in the middle of the destruction phase
                }
            }
        }
        //排序
        if (!applicationListenerBeans.isEmpty()) {
            AnnotationAwareOrderComparator.sort(allListeners);
        }
        return allListeners;
    }
}

CachedListenerRetrieverDefaultListenerRetriever两个类的结构基本一模一样,但是他们的左右不一样,从名字就可以看出来。

CachedListenerRetriever:它存储了监听某种事件的所有监听器,这样发布事件的时候,就没有必要每次从所有的监听器中找

3.3.3 DefaultListenerRetriever(事件多播器存储所有监听器的地方)

/**
 * Helper class that encapsulates a general set of target listeners.
 */
private class DefaultListenerRetriever {

    public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();

    public final Set<String> applicationListenerBeans = new LinkedHashSet<>();

    public Collection<ApplicationListener<?>> getApplicationListeners() {
        List<ApplicationListener<?>> allListeners = new ArrayList<>(
            this.applicationListeners.size() + this.applicationListenerBeans.size());
        allListeners.addAll(this.applicationListeners);
        //getBean方法获取applicationListenerBeans集合名字对应的监听器对象
        if (!this.applicationListenerBeans.isEmpty()) {
            BeanFactory beanFactory = getBeanFactory();
            for (String listenerBeanName : this.applicationListenerBeans) {
                try {
                    ApplicationListener<?> listener =
                        beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    if (!allListeners.contains(listener)) {
                        allListeners.add(listener);
                    }
                }
                catch (NoSuchBeanDefinitionException ex) {
                    // Singleton listener instance (without backing bean definition) disappeared -
                    // probably in the middle of the destruction phase
                }
            }
        }
        //排序
        AnnotationAwareOrderComparator.sort(allListeners);
        return allListeners;
    }
}

总结:

  • applicationListeners集合保存事件多播器中所有的监听器对象
  • applicationListenerBeans集合保存事件多播器中所有的监听器的beanName
  • 唯一的方法getApplicationListeners()会获取到事件多播器中所有的监听器对象,会使用getBean方法得到applicationListenerBeans集合保存的beanName对应的监听器对象。

4 监听器监听事件

为了能够收到发布的事件,我们必须提供监听器监听事件

4.1 spring自动识别监听器

首先,容器启动过程中会自动容器中的监听器,无论监听器是否被实例化

/**
 * Add beans that implement ApplicationListener as listeners.
 * Doesn't affect other listeners, which can be added without being beans.
 */
protected void registerListeners() {
    // Register statically specified listeners first.
    //将已经实例化的listener注册到多播器中
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let post-processors apply to them!
    //获取容器中所有BeanDefinition中的监听器的名字,并注册名字到多播器中,这里没有实例化这些监听器
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // Publish early application events now that we finally have a multicaster...
    //使用多播器发布所有早期事件
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    //使容器中的早期事件集合失效,因为此时已经有事件多播器了,事件可以直接发布,不需要缓存
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

其次,spring还提供了一个ApplicationListenerDetector,它实现了MergedBeanDefinitionPostProcessor接口,ApplicationListenerDetector主要是用来检测这个bean是否实现了ApplicationListener接口,实际就是判断这个bean是不是一个监听器,如果是监听器,就注册到事件多播器中。
下面是这个BeanPostProcessor的两个比较重要的方法

//缓存实例化的监听器名
private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);


//bean实例化后执行
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    //监听器
    if (ApplicationListener.class.isAssignableFrom(beanType)) {
        /**
         * 保存到当前对象singletonNames属性中
         * map集合的value值代表这个监听器是不是单例的
         */
        this.singletonNames.put(beanName, beanDefinition.isSingleton());
    }
}


//bean初始化完成后执行
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean instanceof ApplicationListener) {
        // potentially not detected as a listener by getBeanNamesForType retrieval
        Boolean flag = this.singletonNames.get(beanName);
        //单例的监听器
        if (Boolean.TRUE.equals(flag)) {
            // singleton bean (top-level or inner): register on the fly
            //将监听器添加到应用上下文和事件多播器中
            this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
        }
        //保存非单例的监听器主要是为了输出日志
        else if (Boolean.FALSE.equals(flag)) {
            if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
                // inner bean with other scope - can't reliably process events
                logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                            "but is not reachable for event multicasting by its containing ApplicationContext " +
                            "because it does not have singleton scope. Only top-level listener beans are allowed " +
                            "to be of non-singleton scope.");
            }
            //去掉非单例的监听器缓存
            this.singletonNames.remove(beanName);
        }
    }
    return bean;
}

将监听器添加到应用上下文和事件多播器中

/** Statically specified listeners. */
//上下文中用来保存监听器对象的集合
private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();


@Override
public void addApplicationListener(ApplicationListener<?> listener) {
    Assert.notNull(listener, "ApplicationListener must not be null");
    //有事件多播器就把监听器注册进去,事件多播器创建在3.8章节
    if (this.applicationEventMulticaster != null) {
        this.applicationEventMulticaster.addApplicationListener(listener);
    }
    //保存在上下文中
    this.applicationListeners.add(listener);
}

4.2 自定义监听器监听自定义事件

@Component
public class BlockedListNotifier implements ApplicationListener<BlockedListEvent> {

    private String notificationAddress;

    public void setNotificationAddress(String notificationAddress) {
        this.notificationAddress = notificationAddress;
    }

    @Override
    public void onApplicationEvent(BlockedListEvent event) {
        // notify appropriate parties via notificationAddress...
    }
}
  • 监听器必须交由spring管理,才会生效
  • 必须实现ApplicationListener接口(注解方式另外说)
  • 通过泛型约束来指定该监听器监听的事件类型

5 使用应用事件发布器ApplicationEventPublisher发布事件

先来看一下ApplicationEventPublisher接口

public interface ApplicationEventPublisher {

    //发布ApplicationEvent事件
    default void publishEvent(ApplicationEvent event) {
        publishEvent((Object) event);
    }

    //发布任意事件
    void publishEvent(Object event);

}

这个接口定义了两个方法,一个有类型约束,一个没有,spring推荐使用有类型约束的那个发布事件方法

接下来我们看看publishEvent方法是如何发布事件的。

5.1 注入ApplicationEventPublisher(应用事件发布器)

现在有一个疑问,通过ApplicationEventPublisherAware接口注入进去的是不是容器中的事件多播器ApplicationEventMulticaster呢?很明显不是,它们两个的类型就不一样。那么这个ApplicationEventPublisher对象到底是什么呢?

我们知道通过ApplicationContextAwareProcessor这个BeanPostProcessor可以完成EnvironmentEmbeddedValueResolverResourceLoaderApplicationEventPublisherMessageSourceApplicationContext6个对象注入,下面是注入过程:

/**
 * bean对象初始化之前调用
 */
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    //未实现这些aware接口就什么也不做
    if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
          bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
          bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
        return bean;
    }

    AccessControlContext acc = null;

    if (System.getSecurityManager() != null) {
        acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    }

    if (acc != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareInterfaces(bean);
            return null;
        }, acc);
    }
    else {
        //执行Aware接口方法
        invokeAwareInterfaces(bean);
    }

    return bean;
}

/**
 * 调用这些aware接口set方法                               
 */
private void invokeAwareInterfaces(Object bean) {
    if (bean instanceof EnvironmentAware) {
        ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    }
    if (bean instanceof EmbeddedValueResolverAware) {
        ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    }
    if (bean instanceof ResourceLoaderAware) {
        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    }
    //原来这个ApplicationEventPublisher就是应用上下文对象啊
    if (bean instanceof ApplicationEventPublisherAware) {
        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    }
    if (bean instanceof MessageSourceAware) {
        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    }
    if (bean instanceof ApplicationContextAware) {
        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    }
}

注入的是应用上下文对象

5.2 publishEvent方法发布事件原理

ApplicationEventPublisher接口的方法最终在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 application-specific or a
 * standard framework event)
 */
@Override
public void publishEvent(ApplicationEvent event) {
    publishEvent(event, null);
}

/**
 * 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})
 */
@Override
public void publishEvent(Object event) {
    publishEvent(event, null);
}

两个方法最终都是调用publishEvent(Object event, @Nullable ResolvableType eventType)来完成事件发布

/**
 * 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;
    if (event instanceof ApplicationEvent) {
        applicationEvent = (ApplicationEvent) event;
    }
    //非ApplicationEvent事件
    else {
        //将事件包装为PayloadApplicationEvent
        applicationEvent = new PayloadApplicationEvent<>(this, event);
        //使用ResolvableType解析event事件的类型和适配器PayloadApplicationEvent的泛型约束信息
        if (eventType == null) {
            eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
        }
    }

    // Multicast right now if possible - or lazily once the multicaster is initialized
    //说明此时容器中还未创建事件多播器ApplicationEventMulticaster
    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);
        }
    }
}

获取上下文的事件多播器

/**
 * Return the internal ApplicationEventMulticaster used by the context.
 * @return the internal ApplicationEventMulticaster (never {@code null})
 * @throws IllegalStateException if the context has not been initialized yet
 */
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
    if (this.applicationEventMulticaster == null) {
        throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
                                        "call 'refresh' before multicasting events via the context: " + this);
    }
    //使用上下文的事件多播器,见3.1
    return this.applicationEventMulticaster;
}

从上面我们可以发现,真正执行事件发布是事件多播器ApplicationEventMulticaster

6 spring默认的事件多播器SimpleApplicationEventMulticaster发布事件

multicastEvent方法发布事件

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    //6.1解析获取事件ResolvableType类型
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    //6.2获取异步执行器并执行异步任务
    Executor executor = getTaskExecutor();
    //6.3获取监听对应事件的所有监听器
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
            //6.4执行监听器
            invokeListener(listener, event);
        }
    }
}

6.1 解析获取事件ResolvableType类型

ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));

6.1.1 没有实现ApplicationEvent接口的事件

对于没有实现ApplicationEvent接口的事件,使用ApplicationEventPublisher发布事件的时候,自动适配为PayloadApplicationEvent类型,并且解析事件真实类型和适配器PayloadApplicationEvent的泛型约束信息。见5.2

//将事件包装为PayloadApplicationEvent
applicationEvent = new PayloadApplicationEvent<>(this, event);
//使用ResolvableType解析event事件的类型和适配器PayloadApplicationEvent的泛型约束信息
if (eventType == null) {
    eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}

PayloadApplicationEvent类非常简单,你可以把它理解为适配器,将非ApplicationEvent类型事件适配为ApplicationEvent类型,下面是该类的源码:

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;
    }


    //使用ResolvableType解析event事件的类型和泛型约束信息
    @Override
    public ResolvableType getResolvableType() {
        /**
         * getClass()是获取当前类PayloadApplicationEvent的clazz对象
         * 也就是说不是解析原事件对象的泛型信息
         */
        return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getPayload()));
    }


    //返回原事件对象
    public T getPayload() {
        return this.payload;
    }

}

6.1.2 实现了ApplicationEvent接口的事件

实现了ApplicationEvent接口的事件,则会在此时调用resolveDefaultEventType方法解析事件真实类型。

private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
   return ResolvableType.forInstance(event);
}

最终都是使用ResolvableType.forInstance(event)方法解析事件真实类型。

6.2 获取异步执行器并执行异步任务

//用户可以指定一个异步执行器,事件多播器会自动使用它来执行任务
@Nullable
private Executor taskExecutor;


/**
 * Return the current task executor for this multicaster.
 */
@Nullable
protected Executor getTaskExecutor() {
    return this.taskExecutor;
}

我们可以自定义一个事件多播器,并指定它的异步执行器

<bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster">
    <property name="taskExecutor" ref="taskExecutor"></property>
</bean>

<!--静态工厂方法创建只有一个线程的线程池-->
<bean id="taskExecutor" class="java.util.concurrent.Executors" factory-method="newSingleThreadExecutor"></bean>

6.3获取监听对应事件的所有监听器

/**
 * Return a Collection of ApplicationListeners matching the given
 * event type. Non-matching listeners get excluded early.
 * @param event the event to be propagated. Allows for excluding
 * non-matching listeners early, based on cached matching information.
 * @param eventType the event type
 * @return a Collection of ApplicationListeners
 * @see org.springframework.context.ApplicationListener
 */
protected Collection<ApplicationListener<?>> getApplicationListeners(
    ApplicationEvent event, ResolvableType eventType) {

    //获取事件源对象
    Object source = event.getSource();
    //事件源对象的clazz对象
    Class<?> sourceType = (source != null ? source.getClass() : null);
    //从这里就知道spring是根据事件源对象的类型和事件类型来确定监听器的
    ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

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

    // Quick check for existing entry on ConcurrentHashMap
    //先获取缓存
    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;
        }
        // If result is null, the existing retriever is not fully populated yet by another thread.
        // Proceed like caching wasn't possible for this current local attempt.
    }

    //缓存中没有监听器,就匹配事件多播器中保存的所有监听器,找到能收到该事件的监听器,见6.3.1
    return retrieveApplicationListeners(eventType, sourceType, newRetriever);
}

6.3.1 匹配事件多播器中保存的所有监听器,找到能收到该事件的监听器

/**
 * Actually retrieve the application listeners for the given event and source type.
 * @param eventType the event type
 * @param sourceType the event source type
 * @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes)
 * @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<>();
    Set<ApplicationListener<?>> filteredListeners = (retriever != null ? new LinkedHashSet<>() : null);
    Set<String> filteredListenerBeans = (retriever != null ? new LinkedHashSet<>() : null);

    Set<ApplicationListener<?>> listeners;
    Set<String> listenerBeans;
    synchronized (this.defaultRetriever) {
        //监听器对象
        listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
        //监听器的beanName
        listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
    }

    // Add programmatically registered listeners, including ones coming
    // from ApplicationListenerDetector (singleton beans and inner beans).
    //遍历监听器对象,找到可以接收该事件的监听器
    for (ApplicationListener<?> listener : listeners) {
        //判断listener是否支持该事件类型和事件源对象类型,见6.3.2
        if (supportsEvent(listener, eventType, sourceType)) {
            if (retriever != null) {
                filteredListeners.add(listener);
            }
            allListeners.add(listener);
        }
    }

    // Add listeners by bean name, potentially overlapping with programmatically
    // registered listeners above - but here potentially with additional metadata.
    if (!listenerBeans.isEmpty()) {
        ConfigurableBeanFactory beanFactory = getBeanFactory();
        //遍历监听器beanName,找到可以接收该事件的监听器
        for (String listenerBeanName : listenerBeans) {
            try {
                //早期过滤listenerBeanName对应的监听器,见6.3.4
                if (supportsEvent(beanFactory, listenerBeanName, eventType)) {
                    //实例化
                    ApplicationListener<?> listener =
                        beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                    //再次判断,见6.3.2
                    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 {
                    // Remove non-matching listeners that originally came from
                    // ApplicationListenerDetector, possibly ruled out by additional
                    // BeanDefinition metadata (e.g. factory method generics) above.
                    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()) {
            retriever.applicationListeners = new LinkedHashSet<>(allListeners);
            retriever.applicationListenerBeans = filteredListenerBeans;
        }
        else {
            retriever.applicationListeners = filteredListeners;
            retriever.applicationListenerBeans = filteredListenerBeans;
        }
    }
    return allListeners;
}

6.3.2 判断监听器是否支持该事件类型和事件源对象类型

/**
 * Determine whether the given listener supports the given event.
 * <p>The default implementation detects the {@link SmartApplicationListener}
 * and {@link GenericApplicationListener} interfaces. In case of a standard
 * {@link ApplicationListener}, a {@link GenericApplicationListenerAdapter}
 * will be used to introspect the generically declared type of the target listener.
 * @param listener the target listener to check
 * @param eventType the event type to check against
 * @param sourceType the source type to check against
 * @return whether the given listener should be included in the candidates
 * for the given event type
 */
protected boolean supportsEvent(
    ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {

    //将所有监听器统一适配为GenericApplicationListener
    GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
                                                (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
    //使用GenericApplicationListener类中定义的方法,同时检查监听器是否支持该事件类型和事件源对象类型
    return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}

6.3.3 GenericApplicationListenerGenericApplicationListenerAdapter

GenericApplicationListenerApplicationListener的子接口,该接口额外添加了3个方法,supportsEventType()方法判断该监听器能否处理eventType类型的事件,supportsSourceType()方法判断该监听器能否处理事件源对象类型为sourceType的事件,并且只有这两个方法判断均为true才能断定该监听器能够处理该事件。getOrder()方法指定监听器的优先级

public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
    
    boolean supportsEventType(ResolvableType eventType);

    default boolean supportsSourceType(@Nullable Class<?> sourceType) {
        return true;
    }

    @Override
    default int getOrder() {
        return LOWEST_PRECEDENCE;
    }
}

GenericApplicationListenerAdapter如其名,它是一个监听器适配器,能够将非GenericApplicationListener类型的监听器适配为GenericApplicationListener类型。

public class GenericApplicationListenerAdapter implements GenericApplicationListener, SmartApplicationListener {

    private static final Map<Class<?>, ResolvableType> eventTypeCache = new ConcurrentReferenceHashMap<>();

    //原始的监听器对象
    private final ApplicationListener<ApplicationEvent> delegate;

    //事件类型
    @Nullable
    private final ResolvableType declaredEventType;


    /**
    * Create a new GenericApplicationListener for the given delegate.
    * @param delegate the delegate listener to be invoked
    */
    @SuppressWarnings("unchecked")
    public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
        Assert.notNull(delegate, "Delegate listener must not be null");
        this.delegate = (ApplicationListener<ApplicationEvent>) delegate;
        //构造对象时就解析监听器能够监听的事件类型
        this.declaredEventType = resolveDeclaredEventType(this.delegate);
    }


    //监听器接收事件的方法
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        //调用原始的监听器对象的onApplicationEvent方法
        this.delegate.onApplicationEvent(event);
    }

    //监听器是否支持该事件类型
    @Override
    @SuppressWarnings("unchecked")
    public boolean supportsEventType(ResolvableType eventType) {
        //SmartApplicationListener的支持的事件类型判断
        if (this.delegate instanceof SmartApplicationListener) {
            Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
            return (eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass));
        }
        /**
         * 1.监听器未指定泛型,那么经过resolveDeclaredEventType方法解析结果就为null,表明
         * 监听所有类型事件
         * 2.监听器指定的泛型类型为事件类型的父类或相同
         * 这两种情况都表明该监听器可以接收该种类型的事件
         */
        else {
            return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
        }
    }

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return supportsEventType(ResolvableType.forClass(eventType));
    }

    //监听器是否支持该事件源对象类型
    @Override
    public boolean supportsSourceType(@Nullable Class<?> sourceType) {
        /**
         * 只要我们的监听器不是SmartApplicationListener类型,该方法的返回值总是为true
         * 并且后面的逻辑判断直接忽略
         * 如果要使我们的监听器只能处理特定的事件源对象类型的事件,那我们的监听器只需要实现
         * SmartApplicationListener接口,然后重写supportsSourceType()方法,自定义判断逻辑即可
         */
        return !(this.delegate instanceof SmartApplicationListener) ||
            ((SmartApplicationListener) this.delegate).supportsSourceType(sourceType);
    }

    @Override
    public int getOrder() {
        return (this.delegate instanceof Ordered ? ((Ordered) this.delegate).getOrder() : Ordered.LOWEST_PRECEDENCE);
    }


    @Nullable
    private static ResolvableType resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener) {
        //获取监听器ApplicationListener接口上的泛型信息
        ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass());
        //下面是处理创建了代理的监听器
        if (declaredEventType == null || declaredEventType.isAssignableFrom(ApplicationEvent.class)) {
            Class<?> targetClass = AopUtils.getTargetClass(listener);
            if (targetClass != listener.getClass()) {
                declaredEventType = resolveDeclaredEventType(targetClass);
            }
        }
        return declaredEventType;
    }

    @Nullable
    static ResolvableType resolveDeclaredEventType(Class<?> listenerType) {
        //先从缓存中获取
        ResolvableType eventType = eventTypeCache.get(listenerType);
        if (eventType == null) {
            //获取监听器ApplicationListener接口上的泛型信息
            eventType = ResolvableType.forClass(listenerType).as(ApplicationListener.class).getGeneric();
            //解析的结果放入缓存中
            eventTypeCache.put(listenerType, eventType);
        }
        return (eventType != ResolvableType.NONE ? eventType : null);
    }

}

该类判断非GenericApplicationListener类型的监听器是否支持该事件类型和事件源对象类型

6.3.4 早期过滤listenerBeanName对应的监听器(初步判断是否支持该事件类型)

/**
 * Filter a bean-defined listener early through checking its generically declared
 * event type before trying to instantiate it.
 * <p>If this method returns {@code true} for a given listener as a first pass,
 * the listener instance will get retrieved and fully evaluated through a
 * {@link #supportsEvent(ApplicationListener, ResolvableType, Class)} call afterwards.
 * @param beanFactory the BeanFactory that contains the listener beans
 * @param listenerBeanName the name of the bean in the BeanFactory
 * @param eventType the event type to check
 * @return whether the given listener should be included in the candidates
 * for the given event type
 * @see #supportsEvent(Class, ResolvableType)
 * @see #supportsEvent(ApplicationListener, ResolvableType, Class)
 */
private boolean supportsEvent(
    ConfigurableBeanFactory beanFactory, String listenerBeanName, ResolvableType eventType) {

    //获取名字对应的clazz对象
    Class<?> listenerType = beanFactory.getType(listenerBeanName);
    //监听器的类型为GenericApplicationListener或SmartApplicationListener允许实例化
    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;
    }
}


/**
 * Filter a listener early through checking its generically declared event
 * type before trying to instantiate it.
 * <p>If this method returns {@code true} for a given listener as a first pass,
 * the listener instance will get retrieved and fully evaluated through a
 * {@link #supportsEvent(ApplicationListener, ResolvableType, Class)} call afterwards.
 * @param listenerType the listener's type as determined by the BeanFactory
 * @param eventType the event type to check
 * @return whether the given listener should be included in the candidates
 * for the given event type
 */
protected boolean supportsEvent(Class<?> listenerType, ResolvableType eventType) {
    //早期检查监听器监听的事件类型,见6.3.3
    ResolvableType declaredEventType = GenericApplicationListenerAdapter.resolveDeclaredEventType(listenerType);
    return (declaredEventType == null || declaredEventType.isAssignableFrom(eventType));
}

6.4 执行监听器

/**
 * Invoke the given listener with the given event.
 * @param listener the ApplicationListener to invoke
 * @param event the current event to propagate
 * @since 4.1
 */
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
    //获取异常处理器
    ErrorHandler errorHandler = getErrorHandler();
    if (errorHandler != null) {
        try {
            //调用监听器的监听方法
            doInvokeListener(listener, event);
        }
        //发生异常由异常处理器处理
        catch (Throwable err) {
            errorHandler.handleError(err);
        }
    }
    else {
        doInvokeListener(listener, event);
    }
}

调用监听器的监听方法

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
    try {
        //调用onApplicationEvent方法
        listener.onApplicationEvent(event);
    }
    catch (ClassCastException ex) {
        String msg = ex.getMessage();
        if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
            // Possibly a lambda-defined listener which we could not resolve the generic event type for
            // -> let's suppress the exception and just log a debug message.
            Log logger = LogFactory.getLog(getClass());
            if (logger.isTraceEnabled()) {
                logger.trace("Non-matching event type for listener: " + listener, ex);
            }
        }
        else {
            throw ex;
        }
    }
}

执行过程很简单,就是直接调用ApplicationListener接口的onApplicationEvent()方法

到此为止,基于XML方式的监听器工作原理就已经说完了,下一篇文章我们来看基于注解的监听器是如何工作的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值