Skip to content

事件通知机制

一、核心组件概述

Spring事件机制遵循观察者模式(Observer Pattern),核心组件包括:

  1. 事件(Event):继承ApplicationEvent的对象,代表发生的具体事件(如容器刷新、Bean初始化完成等)。
  2. 监听者(Listener):实现ApplicationListener接口或使用@EventListener注解的方法,负责处理事件。
  3. 发布者(Publisher):实现ApplicationEventPublisher接口的对象(通常由ApplicationContext担任),负责发布事件。
  4. 多播器(Multicaster):实现ApplicationEventMulticaster接口的对象(默认是SimpleApplicationEventMulticaster),负责将事件转发给所有符合条件的监听者,是事件机制的调度中心

二、事件机制的初始化流程

事件机制的初始化伴随ApplicationContext的启动(refresh()方法),主要分为两步:初始化多播器注册监听者

1. 初始化多播器(initApplicationEventMulticaster)

AbstractApplicationContextrefresh()方法中,会调用initApplicationEventMulticaster()初始化多播器:

java
protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 1. 优先使用容器中自定义的多播器(bean名称必须为"applicationEventMulticaster")
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    } else {
        // 2. 否则使用默认的SimpleApplicationEventMulticaster
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    }
}
  • 关键逻辑
    • 若容器中存在名为applicationEventMulticasterApplicationEventMulticaster bean,优先使用它(自定义多播器)。
    • 否则创建默认的SimpleApplicationEventMulticaster,并注册为单例bean。

2. 注册监听者(registerListeners)

refresh()方法中,接着调用registerListeners()注册所有监听者:

java
protected void registerListeners() {
    // 1. 注册静态监听者(通过addApplicationListener()手动添加的)
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // 2. 注册容器中所有实现ApplicationListener接口的bean(通过bean名称注册,避免提前初始化)
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // 3. 处理早期事件(多播器初始化前发布的事件,暂存于earlyApplicationEvents)
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}
  • 关键逻辑
    • 静态监听者:通过ApplicationContext.addApplicationListener()手动添加的监听者,直接注册到多播器。
    • 动态监听者:容器中所有实现ApplicationListener接口的bean,通过addApplicationListenerBean()注册(仅注册bean名称,待事件发布时才初始化bean)。
    • 早期事件:若在多播器初始化前发布事件(如BeanFactoryPostProcessor执行时),会暂存于earlyApplicationEvents,待多播器初始化后再处理。

三、事件发布与传播流程

事件发布的入口是ApplicationContext.publishEvent()方法,底层通过多播器将事件转发给监听者。

1. 事件发布(publishEvent)

AbstractApplicationContextpublishEvent()方法负责发布事件:

java
@Override
public void publishEvent(Object event) {
    publishEvent(event, null);
}

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
    Assert.notNull(event, "Event must not be null");

    // 1. 将事件包装为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();
        }
    }

    // 2. 处理早期事件(多播器未初始化时,暂存)
    if (this.earlyApplicationEvents != null) {
        this.earlyApplicationEvents.add(applicationEvent);
    } else {
        // 3. 调用多播器转发事件
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }

    // 4. 向父容器发布事件(若有父容器)
    if (this.parent != null) {
        if (this.parent instanceof AbstractApplicationContext) {
            ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
        } else {
            this.parent.publishEvent(event);
        }
    }
}
  • 关键逻辑
    • 事件包装:非ApplicationEvent的对象会被包装为PayloadApplicationEvent(携带事件源ApplicationContext)。
    • 早期事件处理:若多播器未初始化(如refresh()前),事件暂存于earlyApplicationEvents
    • 多播器转发:调用多播器的multicastEvent()方法转发事件。
    • 父容器传播:事件会向父容器递归发布(若有父容器)。

2. 事件多播(multicastEvent)

SimpleApplicationEventMulticastermulticastEvent()方法是事件传播的核心,负责将事件转发给所有符合条件的监听者:

java
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    // 1. 获取符合条件的监听者(过滤、排序)
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        // 2. 异步执行(若配置了Executor)
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        } else {
            // 3. 同步执行(默认)
            invokeListener(listener, event);
        }
    }
}
  • 关键逻辑
    • 事件类型解析:通过ResolvableType解析事件的具体类型(如ContextRefreshedEvent)。
    • 监听者筛选:调用getApplicationListeners()获取所有符合条件的监听者(过滤、排序)。
    • 执行方式:若配置了Executor(如线程池),则异步执行;否则同步执行(默认)。
    • 调用监听者:通过invokeListener()调用监听者的onApplicationEvent()方法。

3. 监听者筛选(getApplicationListeners)

AbstractApplicationEventMulticastergetApplicationListeners()方法负责筛选符合条件的监听者:

java
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {
    Object source = event.getSource();
    Class<?> sourceType = (source != null ? source.getClass() : null);
    // 1. 构建缓存键(事件类型+源类型)
    ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

    // 2. 从缓存获取(避免重复筛选)
    ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
    if (retriever != null) {
        return retriever.getApplicationListeners();
    }

    // 3. 同步构建缓存(若缓存未命中)
    synchronized (this.retrievalMutex) {
        retriever = this.retrieverCache.get(cacheKey);
        if (retriever != null) {
            return retriever.getApplicationListeners();
        }
        retriever = new ListenerRetriever(true);
        // 4. 筛选监听者(核心逻辑)
        Collection<ApplicationListener<?>> listeners = retrieveApplicationListeners(eventType, sourceType, retriever);
        this.retrieverCache.put(cacheKey, retriever);
        return listeners;
    }
}
  • 关键逻辑
    • 缓存机制:使用ListenerCacheKey(事件类型+源类型)作为缓存键,避免重复筛选。
    • 同步构建:若缓存未命中,同步构建缓存(避免并发问题)。
    • 筛选逻辑:调用retrieveApplicationListeners()筛选符合条件的监听者。

4. 监听者匹配(retrieveApplicationListeners)

retrieveApplicationListeners()方法遍历所有注册的监听者,通过supportsEvent()方法判断是否匹配:

java
protected Collection<ApplicationListener<?>> retrieveApplicationListeners(
        ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {
    List<ApplicationListener<?>> allListeners = new ArrayList<>();
    Set<ApplicationListener<?>> listeners;
    Set<String> listenerBeans;

    // 1. 获取所有注册的监听者(实例+bean名称)
    synchronized (this.retrievalMutex) {
        listeners = new LinkedHashSet<>(this.applicationListeners);
        listenerBeans = new LinkedHashSet<>(this.applicationListenerBeans);
    }

    // 2. 处理bean名称注册的监听者(动态初始化)
    for (String listenerBeanName : listenerBeans) {
        try {
            Class<?> listenerType = getBeanFactory().getType(listenerBeanName);
            if (listenerType != null && isListenerTypeMatch(listenerType, eventType)) {
                ApplicationListener<?> listener = getBeanFactory().getBean(listenerBeanName, ApplicationListener.class);
                if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
                    allListeners.add(listener);
                    if (retriever != null) {
                        retriever.addApplicationListener(listener);
                    }
                }
            }
        } catch (NoSuchBeanDefinitionException ex) {
            // 忽略已销毁的bean
        }
    }

    // 3. 处理实例注册的监听者(静态)
    for (ApplicationListener<?> listener : listeners) {
        if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
            allListeners.add(listener);
            if (retriever != null) {
                retriever.addApplicationListener(listener);
            }
        }
    }

    // 4. 排序(按@Order或Ordered接口)
    AnnotationAwareOrderComparator.sort(allListeners);
    if (retriever != null && retriever.isCacheable()) {
        retriever.setApplicationListeners(allListeners);
    }
    return allListeners;
}
  • 关键逻辑
    • 动态监听者:通过bean名称注册的监听者,需要从BeanFactory获取实例(延迟初始化),并判断是否匹配。
    • 静态监听者:通过实例注册的监听者,直接判断是否匹配。
    • 匹配逻辑:调用supportsEvent()方法判断监听者是否支持当前事件类型和源类型。
    • 排序:使用AnnotationAwareOrderComparator对监听者排序(@Order注解或Ordered接口,值越小优先级越高)。

5. 监听者匹配规则(supportsEvent)

supportsEvent()方法根据监听者的类型,判断是否支持当前事件:

java
protected boolean supportsEvent(
        ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
    // 1. SmartApplicationListener:支持事件类型+源类型过滤
    if (listener instanceof SmartApplicationListener) {
        SmartApplicationListener smartListener = (SmartApplicationListener) listener;
        return smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType);
    }
    // 2. GenericApplicationListener:支持泛型事件类型过滤
    else if (listener instanceof GenericApplicationListener) {
        return ((GenericApplicationListener) listener).supportsEventType(eventType);
    }
    // 3. 普通ApplicationListener:根据泛型参数判断(如ApplicationListener<ContextRefreshedEvent>)
    else {
        Class<?> listenerEventType = resolveListenerEventType(listener);
        return (listenerEventType == null || eventType.isAssignableFrom(listenerEventType));
    }
}
  • 关键逻辑
    • SmartApplicationListener:需同时满足supportsEventType()(事件类型)和supportsSourceType()(源类型)。
    • GenericApplicationListener:支持泛型事件类型(如ApplicationListener<PayloadApplicationEvent<String>>)。
    • 普通ApplicationListener:根据泛型参数判断(如ApplicationListener<ContextRefreshedEvent>仅处理ContextRefreshedEvent及其子类)。

四、@EventListener注解的实现原理

@EventListener是Spring 4.2引入的注解,用于将普通方法转换为事件监听者。其底层通过EventListenerMethodProcessorBeanPostProcessor)实现。

1. EventListenerMethodProcessor的作用

EventListenerMethodProcessor实现了BeanPostProcessorSmartInitializingSingleton接口,负责扫描带有@EventListener的方法,并将其转换为ApplicationListener

(1)扫描@EventListener方法(postProcessAfterInitialization)

postProcessAfterInitialization方法在bean初始化后执行,扫描bean中的@EventListener方法:

java
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof AopInfrastructureBean || bean instanceof EventListenerFactory ||
            bean instanceof EventListenerMethodProcessor) {
        return bean;
    }

    // 获取bean的目标类(避免代理类影响)
    Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
    if (!this.nonAnnotatedClasses.contains(targetClass)) {
        // 扫描带有@EventListener的方法
        Map<Method, EventListener> annotatedMethods = MethodIntrospector.selectMethods(targetClass,
                (MethodIntrospector.MetadataLookup<EventListener>) method ->
                        AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
        if (CollectionUtils.isEmpty(annotatedMethods)) {
            this.nonAnnotatedClasses.add(targetClass);
        } else {
            // 处理每个@EventListener方法
            for (Map.Entry<Method, EventListener> entry : annotatedMethods.entrySet()) {
                Method method = entry.getKey();
                EventListener annotation = entry.getValue();
                processEventListener(method, annotation, bean, beanName, this.applicationContext);
            }
        }
    }
    return bean;
}
  • 关键逻辑
    • 跳过特殊bean(如AOP基础设施bean、事件监听工厂等)。
    • 扫描目标类中的@EventListener方法(使用MethodIntrospector)。
    • 处理每个@EventListener方法(调用processEventListener())。

(2)转换为ApplicationListener(processEventListener)

processEventListener方法将@EventListener方法转换为ApplicationListenerMethodAdapterApplicationListener的实现类):

java
protected void processEventListener(Method method, EventListener annotation, Object bean, String beanName,
        ApplicationContext context) {
    // 选择可调用的方法(避免代理方法)
    Method methodToUse = AopUtils.selectInvocableMethod(method, bean.getClass());
    // 使用EventListenerFactory创建ApplicationListener(默认是DefaultEventListenerFactory)
    ApplicationListener<?> applicationListener = this.eventListenerFactory.createApplicationListener(beanName, bean.getClass(), methodToUse);
    if (applicationListener instanceof ApplicationListenerMethodAdapter) {
        // 初始化适配器(注入ApplicationContext和SpEL表达式 evaluator)
        ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
    }
    // 将ApplicationListener注册到容器
    context.addApplicationListener(applicationListener);
}
  • 关键逻辑
    • 方法选择:使用AopUtils.selectInvocableMethod()选择可调用的方法(避免代理类的方法)。
    • 适配器创建:通过EventListenerFactory创建ApplicationListenerMethodAdapter(默认是DefaultEventListenerFactory)。
    • 注册监听者:将ApplicationListenerMethodAdapter注册到ApplicationContext(最终会被添加到多播器)。

2. ApplicationListenerMethodAdapter的作用

ApplicationListenerMethodAdapter实现了ApplicationListener接口,负责将事件转发给@EventListener方法:

java
@Override
public void onApplicationEvent(ApplicationEvent event) {
    processEvent(event);
}

protected void processEvent(ApplicationEvent event) {
    // 解析方法参数(如事件对象、源对象、@Payload参数等)
    Object[] args = resolveArguments(event);
    // 判断是否需要处理(如@EventListener的condition属性)
    if (shouldHandle(event, args)) {
        // 调用目标方法
        invokeMethod(args);
    }
}
  • 关键逻辑
    • 参数解析:resolveArguments()方法解析@EventListener方法的参数(如event对象、source对象、@Payload注解的参数等)。
    • 条件判断:shouldHandle()方法判断是否需要处理事件(如@EventListener(condition = "#event.source == 'test'")中的SpEL表达式)。
    • 方法调用:invokeMethod()方法调用目标方法(使用反射)。

3. @EventListener的条件过滤(condition属性)

@EventListenercondition属性支持SpEL表达式,用于过滤事件。例如:

java
@EventListener(condition = "#event.source == 'mySource'")
public void handleEvent(MyEvent event) {
    // 处理事件
}

shouldHandle()方法会评估condition表达式:

java
protected boolean shouldHandle(ApplicationEvent event, Object[] args) {
    if (this.condition == null) {
        return true;
    }
    // 使用SpelExpressionEvaluator评估condition表达式
    EvaluationContext evaluationContext = createEvaluationContext(event, args);
    return this.evaluator.evaluate(this.condition, evaluationContext, Boolean.class);
}
  • 关键逻辑
    • 创建EvaluationContext(包含事件对象、方法参数等变量)。
    • 使用SpelExpressionEvaluator评估condition表达式,返回true则处理事件。

五、异步事件处理

Spring事件默认是同步执行的(发布者会阻塞直到所有监听者执行完成)。若需异步执行,需配置Executor(线程池)。

1. 配置异步多播器

通过自定义ApplicationEventMulticaster bean,设置Executor

java
@Configuration
public class AsyncEventConfig {
    @Bean(name = AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)
    public ApplicationEventMulticaster applicationEventMulticaster() {
        SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
        // 设置线程池(如ThreadPoolTaskExecutor)
        multicaster.setExecutor(taskExecutor());
        return multicaster;
    }

    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(20);
        executor.initialize();
        return executor;
    }
}

2. 异步执行的源码逻辑

SimpleApplicationEventMulticastermulticastEvent()方法中,若Executor不为null,则使用线程池异步执行:

java
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        if (executor != null) {
            // 异步执行(提交到线程池)
            executor.execute(() -> invokeListener(listener, event));
        } else {
            // 同步执行(默认)
            invokeListener(listener, event);
        }
    }
}
  • 关键逻辑
    • Executor不为null,则将监听者的onApplicationEvent()方法提交到线程池执行(异步)。
    • 否则同步执行(默认)。

六、内置事件

Spring提供了多个内置事件,用于通知容器的生命周期状态:

事件类名发布时机
ContextRefreshedEvent容器刷新完成(refresh()方法执行完毕)
ContextStartedEvent容器启动(start()方法执行完毕)
ContextStoppedEvent容器停止(stop()方法执行完毕)
ContextClosedEvent容器关闭(close()方法执行完毕)
BeanFactoryPostProcessorEventBeanFactoryPostProcessor执行完毕
ApplicationReadyEvent应用准备就绪(所有bean初始化完成)

内置事件的发布示例(ContextRefreshedEvent)

AbstractApplicationContextfinishRefresh()方法中发布ContextRefreshedEvent

java
protected void finishRefresh() {
    // 清除资源缓存
    clearResourceCaches();
    // 初始化生命周期处理器
    initLifecycleProcessor();
    // 通知生命周期处理器刷新完成
    getLifecycleProcessor().onRefresh();
    // 发布ContextRefreshedEvent
    publishEvent(new ContextRefreshedEvent(this));
    // 注册到LiveBeansView(用于监控)
    LiveBeansView.registerApplicationContext(this);
}

七、扩展与自定义

Spring事件机制支持灵活扩展,常见的自定义场景包括:

1. 自定义事件

继承ApplicationEvent或使用PayloadApplicationEvent(无需继承):

java
// 自定义事件(继承ApplicationEvent)
public class MyEvent extends ApplicationEvent {
    private String message;

    public MyEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    // getter/setter
}

// 使用PayloadApplicationEvent(无需继承)
applicationContext.publishEvent("myPayload"); // 会被包装为PayloadApplicationEvent<String>

2. 自定义监听者

  • 实现ApplicationListener接口:
    java
    @Component
    public class MyEventListener implements ApplicationListener<MyEvent> {
        @Override
        public void onApplicationEvent(MyEvent event) {
            System.out.println("处理MyEvent:" + event.getMessage());
        }
    }
  • 使用@EventListener注解:
    java
    @Component
    public class MyEventListener {
        @EventListener
        public void handleMyEvent(MyEvent event) {
            System.out.println("处理MyEvent:" + event.getMessage());
        }
    }

3. 自定义多播器

实现ApplicationEventMulticaster接口(或继承AbstractApplicationEventMulticaster):

java
@Component(AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)
public class MyEventMulticaster extends AbstractApplicationEventMulticaster {
    @Override
    public void multicastEvent(ApplicationEvent event) {
        // 自定义多播逻辑(如过滤、异步执行等)
        for (ApplicationListener<?> listener : getApplicationListeners(event)) {
            listener.onApplicationEvent(event);
        }
    }

    @Override
    public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
        // 自定义多播逻辑
    }
}

八、总结

Spring事件通知机制的核心逻辑是:

  1. 初始化:容器启动时初始化多播器(SimpleApplicationEventMulticaster),并注册所有监听者。
  2. 发布事件:通过ApplicationContext.publishEvent()发布事件,底层调用多播器的multicastEvent()方法。
  3. 事件传播:多播器筛选符合条件的监听者(根据事件类型、源类型、@Order顺序),并同步/异步执行监听者的方法。
  4. 注解支持@EventListener注解通过EventListenerMethodProcessor转换为ApplicationListenerMethodAdapter,实现方法级别的事件监听。

通过这种机制,Spring实现了组件间的解耦(发布者无需知道监听者的存在),并支持同步/异步事件过滤顺序控制等灵活特性,是Spring生态中重要的扩展点之一。

关键源码类总结

  • 容器初始化:AbstractApplicationContextrefresh()initApplicationEventMulticaster()registerListeners())。
  • 多播器:SimpleApplicationEventMulticastermulticastEvent())。
  • 监听者处理:EventListenerMethodProcessorpostProcessAfterInitialization())、ApplicationListenerMethodAdapteronApplicationEvent())。
  • 事件类:ApplicationEventPayloadApplicationEvent
  • 工具类:AnnotationAwareOrderComparator(排序)、ResolvableType(事件类型解析)。