laitimes

浅谈业务解耦小工具 - Spring Event

author:Flash Gene

1. What it is

Official Website Definition

"An event is an object that is created when something notable happens within an application, such as a user clicking a button or an HTTP request arriving at a web server. An event listener is an object that listens for events, and the code that handles the event is the event handler. Event handlers are invoked by an event publisher. The act of invoking an event is called publishing an event."

The definition emphasizes the concepts of events, event listeners, and event handlers, and treats events as objects created by meaningful actions in an application. At the same time, the role of event listeners and event handlers is explicitly described as listening to events and responding. In addition, the official definition mentions the concept of event publisher and publishing event.

Spring Event is an event-driven model in the Spring framework that can be used to pass messages and respond to events between different components.

Merit:

  • Reduced coupling between components: By using Spring Event, components don't need to explicitly reference each other, but interact with each other through events, reducing the degree of coupling between them.
  • Improve the scalability of your application: Because of the reduced coupling between components, it's easier to add or remove components when your application needs to be expanded or modified.
  • Improve code reusability: Because the event listener is a single component, it can be reused by multiple event sources, increasing code reusability.
  • Provides support for asynchronous event processing: Spring Event can provide support for asynchronous event processing, which avoids blocking of event processing and improves the performance of your application.
  • Easy to test and simulate events: Because the event mechanism is loosely coupled, it's easy to test and simulate events, which improves the testability of your code.
  • Overall, Spring Event provides a loosely coupled mechanism for interacting with components through events, making applications more flexible, scalable, and testable.

☢️Shortcoming:

  • Overuse of the event mechanism can lead to increased code complexity: Excessive use of the event mechanism in an application can lead to a complex code structure, which can make it difficult to maintain and scale the program.
  • Can affect the performance of the application: In event processing, when the number of events is high, the execution of the event listener can consume more CPU resources, which can affect the performance of the application.
  • Potentially out-of-order execution of events: Because Spring Events are implemented based on the observer pattern, the order of execution between event listeners is not deterministic, which can lead to out-of-order execution of events.
  • Can cause some difficulty in debugging: Because the triggering and handling of events in the event mechanism is often asynchronous, you may encounter some difficulties when debugging your application.

Therefore, when using Spring Event, developers should judge whether they need to use the event mechanism according to their specific business needs and scenarios, and make reasonable use of this mechanism to optimize the architecture of the application.

2. How to use it

Define the event

Inherit from ApplicationEvent to wrap the event information that needs to be passed as a business event class, as shown below.

java复制代码public class FinishLvEvent extends ApplicationEvent {

    /**
     * 闯关结果
     */
    private String result;

    /**
     * 事件处理后返回内容容器
     */
    private Object response;

    //getter setter...

    public FinishLvEvent(Object source, String result, Object response) {
        super(source);
        this.result = result;
        this.response = response;
    }
}           

Event release

注入ApplicationEventPublisher,通过publishEvent方法即可发布事件。 ApplicationEventPublisher的一般实现是AbstractApplicationContext,即Spring容器本身就是可以发送Spring事件。

java复制代码@Service
public class AuditService {

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void audit(int auditStatus, long auditId) {
        // 修改数据库审核状态
        auditMapper.updateStatusById(auditStatus, auditId);
        // 发送审核事件
        applicationEventPublisher.publishEvent(new AuditEvent(this, auditStatus, auditId));
    }
}           

Event listening

To implement the listener of the corresponding event, you need to inherit from ApplicationListener and implement the onApplicationEvent method. Specify the class of events that need to be listened to through generics.

java复制代码@Component
public class AuditEventListener implements ApplicationListener<AuditEvent> {

    @Override
    public void onApplicationEvent(AuditEvent auditEvent) {
        // 事件处理
    }
}           

You can also use @EventListener annotation method to wrap it as an event handler. It is suitable for:

1. You don't want to create an ApplicationListener implementation class for each event handling;

2. Want to support more complex event condition filtering.

The @EventListener classes property can filter the event type, while the condition property can filter events based on whether the event object satisfies a conditional expression.

java复制代码@Component
public class EventProcessor {

    @EventListener(classes={CustomEvent.class}, condition="#event.status==1")
    public void process(CustomEvent event) {
        // 事件处理
    }
}           

Asynchronous processing

By default, the ApplicationListener handles events synchronously. If you want to handle time-consuming operations and want to execute them asynchronously, there are three options:

1. 自定义ApplicationEventMulticaster

As you can see later, the Spring container will preferentially use the bean with beanName as applicationEventMulticater as the event forwarding handler, and if it does not exist, it will use SimpleApplicationEventMulticaster as the event forwarding handler by default, which is executed synchronously by default. However, it supports setting up an Executor, so we can use a custom thread pool handler as an Executor to support asynchronous execution.

java复制代码@Configuration
public class Config {

    @Bean
    public SimpleApplicationEventMulticaster applicationEventMulticater() {
        SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
        multicaster.setTaskExecutor(Executors.newFixedThreadPool(1));  // 自定义线程池
        return multicaster;
    }
}           

However, when this is set, all listeners are executed asynchronously. For applications that need to support both asynchronous and synchronous execution, consider the following scenario.

2. Manually commit the thread pool for asynchronous execution

Suitable for simple scenes. But this is more intrusive to the code.

java复制代码private Executor executor = Executors.newFixedThreadPool(1);

public void onApplicationEvent(CustomEvent event) {
    executor.execute(() -> process(event));
}           

3. Use @Async annotations

For method handlers that @EventListener annotations, you can use @Async annotations to make the method call asynchronous. (You need to use @EnableAsync annotations on the startup Application to introduce support for @Async.) )

3. Source code analysis

Core classes, methods

浅谈业务解耦小工具 - Spring Event
  • ApplicationEvent

Abstract Class: All Spring Events inherit from this abstract class. It defines a source field that represents the event source, along with the associated getter and setter methods.

  • ApplicationListener

Interface: All Spring Event listeners need to implement this interface to implement the onApplicationEvent() method to handle events.

  • ApplicationEventPublisher

Interface: Event publisher, defines the publishEvent() method, which is used to publish events.

  • ApplicationEventPublisherAware

Interface: By implementing this interface, the bean is aware of the event publisher and saves it in a member variable.

  • ApplicationEventMulticaster

接口:事件广播器,用于将事件广播给所有的监听器。 Spring 默认提供了 SimpleApplicationEventMulticaster 和 AsyncApplicationEventMulticaster 两种实现。

  • AbstractApplicationEventMulticaster

抽象类:实现了 ApplicationEventMulticaster 接口的大部分方法,提供了一些基础的实现逻辑。 SimpleApplicationEventMulticaster 和 AsyncApplicationEventMulticaster 都继承自该类。

  • GenericApplicationListener

Interface: This is a subinterface of the ApplicationListener interface and defines a generic type E that specifies the type of event to listen to.

  • SimpleApplicationEventMulticaster

Class: Implements the ApplicationEventMulticaster interface, which is used to broadcast events to all listeners.

  • AsyncApplicationEventMulticaster

Class: Implements the ApplicationEventMulticaster interface to asynchronously broadcast events to all listeners.

  • ApplicationEventPublisherAwareProcessor

Class: Implements the BeanPostProcessor interface to automatically inject event publishers into beans that implement the ApplicationEventPublisherAware interface.

These classes and interfaces are at the heart of Spring Events, and they provide important functionality such as event definition, listener registration and handling, event publisher injection, and more.

Reservation events

There are several events reserved in the Spring Framework, including but not limited to the following:

ContextRefreshedEvent:在 ApplicationContext 被初始化或刷新时,该事件被发布。 这也可以在 ConfigurableApplicationContext 接口中使用 refresh() 方法来发生。

ContextStartedEvent:在启动时,该事件被发布,即在调用 ConfigurableApplicationContext 接口中的 start() 方法时。

ContextStoppedEvent:在停止时,该事件被发布,即在调用 ConfigurableApplicationContext 接口中的 stop() 方法时。

ContextClosedEvent:在 ApplicationContext 被关闭时,该事件被发布。 这也可以在 ConfigurableApplicationContext 接口中使用 close() 方法来发生。

RequestHandledEvent: This event is published after the web request has been processed. This event is only available for web modules that use Spring.

ServletRequestHandledEvent: This event is published after the web request has been processed. This event is only available for web modules that use Spring.

SessionDestroyedEvent: This event is published when a web session is destroyed. This event is only available for web modules that use Spring.

Extend the demo based on reserved events

Publish the custom event when you're done. Can be used

@EventListener 注解或 ApplicationListener 接口来监听 ContextRefreshedEvent 事件,例如:

java复制代码@Component
public class MyContextRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 发布自定义事件
        event.getApplicationContext().publishEvent(new MyContextRefreshedEvent(this));
    }
}           

Create a<MyContextRefreshedEvent> custom event listener that inherits from the ApplicationListener and implement the onApplicationEvent method to perform the custom initialization operation. For example, you can create a MyContextRefreshedEventListener class:

java复制代码@Component
public class MyContextRefreshedEventListener implements ApplicationListener<MyContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(MyContextRefreshedEvent event) {
        // 执行自定义的初始化操作
        System.out.println("MyContextRefreshedEvent received, do some initialization...");
    }
}           

Through the above steps, when the Spring container is started, the ContextRefreshedEvent event will be triggered, and the MyContextRefreshedEvent custom event will be published, and the custom event listener MyContextRefreshedEventListener will be used to perform the custom initialization operation.

Events are published and forwarded

浅谈业务解耦小工具 - Spring Event

ApplicationEventPublisher

Spring容器(父类AbstractApplicationContext)把自身作为ApplicationEventPublisher类的实现注册到容器中

java复制代码// AbstractApplicationContext#prepareBeanFactory
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);           

Finally, register the type and instance to:

java复制代码private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);           

AbstractApplicationContext作为ApplicationEventPublisher,实现了publishEvent方法,将其转发给内部实现:

  1. 包装非AppilationNevent对象为PaylodaplicationEvent
  2. Save earlier published events before the listener initializes
  3. 在初始化之后直接给交给applicationEventMulticaster发布事件
  4. Also publish the event to the parent container (if any, and it is an AbstractApplicationContext implementation)
java复制代码// AbstractApplicationContext
@Override
public void publishEvent(ApplicationEvent event) {
    publishEvent(event, null);
}

@Override
public void publishEvent(Object event) {
    publishEvent(event, null);
}
// 具体实现
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
    // 包装ApplicationEvent
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent) {
        applicationEvent = (ApplicationEvent) event;
    }
    else {
        applicationEvent = new PayloadApplicationEvent<>(this, event);
        if (eventType == null) {
            eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
        }
    }
    // 考虑到部分事件在Listener注册之前就发布了,因此先保存起来
    if (this.earlyApplicationEvents != null) {
        this.earlyApplicationEvents.add(applicationEvent);
    }
    else {
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }
    // 同时给父容器发布事件
    if (this.parent != null) {
        if (this.parent instanceof AbstractApplicationContext) {
            ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
        }
        else {
            this.parent.publishEvent(event);
        }
    }
}           

也就是事件转发依赖ApplicationEventMulticaster对象。 容器初始化过程中会先完成ApplicationEventMulticaster对象的初始化,再注册Listener。

text复制代码// AbstractApplicationContext
public void refresh() {
    prepareRefresh();
    ...
    initApplicationEventMulticaster();
    onRefresh();
    registerListeners(); // 注册监听器
    ...
}           

Use a bean named applicationEventMulticaster if the container is already registered (we can register a custom ApplicationEventMulticaster this way, like adding a thread handler), otherwise use SimpleApplicationEventMulticaster as the forwarder by default.

text复制代码public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    }
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    }
}           

将容器注册的Listener和Listener Bean,注册到applicationEventMulticaster。 同时开始转发早期收集的事件。

text复制代码protected void registerListeners() {
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }
    // 从容器中获取实现ApplicationListener的Bean
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }
    // 初始化之前收集的事件,这时候开始转发
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}           
关于earlyApplicationEventsAbstractApplicationContext的refresh()方法确定了容器初始化的流程,在prepareRefresh()中将earlyApplicationEvents初始化𰵚空列表,再此之后初始化过程中发送的事件,都将保存在earlyApplicationEvents中。 而后续先初始化applicationEventMulticaster,再注册完监听器,此时会将earlyApplicationEvents中所有事件发送给监听器,然后置为null,至此earlyApplicationEvents的任务就已经完成了。

SimpleApplicationEventMulticaster

SimpleApplicationEventMulticaster 继承自AbstractApplicationEventMulticaster ,后者实现了Listener和Listener Bean注册和移除、查找,前者在此基础上,实现了事件转发的功能。 在multicastEvent方法中,遍历所有支持该事件类型的ApplicationListener,调用其onApplicationEvent方法。 SimpleApplicationEventMulticaster 允许用户设置Executor,使用Executor执行事件处理程序。

java复制代码// SimpleApplicationEventMulticaster
@Override
public void multicastEvent(ApplicationEvent event) {
    multicastEvent(event, resolveDefaultEventType(event));
}

@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 {
            // 执行 listener.onApplicationEvent(event);
            invokeListener(listener, event);
        }
    }
}           

AbstractApplicationEventMulticaster 的 defaultRetriever (ListenerRetriever 类型)负责维护两个列表applicationListeners 和 applicationListenerBeans。 Listener和Listener Bean的注册和移除都是对这两个列表的新增和删除。 (为什么需要Listener Bean?支持1. 非singleton bean;2. FactoryBean)

java复制代码@Override
public void addApplicationListener(ApplicationListener<?> listener) {
    synchronized (this.retrievalMutex) {
        Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
        if (singletonTarget instanceof ApplicationListener) {
            this.defaultRetriever.applicationListeners.remove(singletonTarget);
        }
        this.defaultRetriever.applicationListeners.add(listener);
        this.retrieverCache.clear();
    }
}

@Override
public void removeApplicationListener(ApplicationListener<?> listener) {
    synchronized (this.retrievalMutex) {
        this.defaultRetriever.applicationListeners.remove(listener);
        this.retrieverCache.clear();
    }
}           

每次事件转发需要查询支持该事件类型的ApplicationListener:从defaultRetriever 维护的applicationListeners和applicationListenerBeans找到适用类型的ApplicationListener对象。 最后按照Order优先级排序,并返回。

java复制代码// 对于listenerBean来说,需要从容器中获取对应的Bean对象
Class<?> listenerType = beanFactory.getType(listenerBeanName);
if (listenerType == null || supportsEvent(listenerType, eventType)) {
    ApplicationListener<?> listener =
    beanFactory.getBean(listenerBeanName, ApplicationListener.class);
    if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
        allListeners.add(listener);
    }
}           

To avoid traversing each query, use retrieverCache as the cache, so that for the same event type, the corresponding ApplicationListener list can be directly returned. That's why every time a listener or listenerBean is added or removed, the retrieverCache must be emptied.

java复制代码protected Collection<ApplicationListener<?>> getApplicationListeners(
        ApplicationEvent event, ResolvableType eventType) {
    Object source = event.getSource();
    Class<?> sourceType = (source != null ? source.getClass() : null);
    ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
    // 直接查询缓存
    ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
    if (retriever != null) {
        return retriever.getApplicationListeners();
    }
    if (this.beanClassLoader == null ||
            (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
                    (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
        synchronized (this.retrievalMutex) {
            retriever = this.retrieverCache.get(cacheKey);
            if (retriever != null) {
                return retriever.getApplicationListeners();
            }
            retriever = new ListenerRetriever(true);
            Collection<ApplicationListener<?>> listeners =
                    retrieveApplicationListeners(eventType, sourceType, retriever);
            this.retrieverCache.put(cacheKey, retriever);
            return listeners;
        }
    }
    else {
        // 不能安全使用缓存
        return retrieveApplicationListeners(eventType, sourceType, null);
    }
}           

@EventListener & EventListenerMethodProcessor

AnnotationConfigUtils给容器提供了一些默认的注解处理器。 包括EventListenerMethodProcessor方法注解处理器和默认的EventListenerFactory实现。

java复制代码// AnnotationConfigUtils#registerAnnotationConfigProcessors
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
    RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
    def.setSource(source);
    beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}

if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
    RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
    def.setSource(source);
    beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}           

EventListenerMethodProcessor做了以下几件事:

  1. Get the implementation of all EventListenerFactory interfaces from the bean container (order sorting)
  2. After the container initializes the singleton object, it iterates through the classes of all beans in the container, and parses the method of @EventListener annotations in the class through reflection
  3. Call these methods via the appropriate EventListenerFactory

createApplicationListener 包装成ApplicationListener对象,并注册到ApplicationContext

java复制代码// 1. 从Bean容器中获取所有EventListenerFactory接口的实现
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    this.beanFactory = beanFactory;
    Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
    List<EventListenerFactory> factories = new ArrayList<>(beans.values());
    AnnotationAwareOrderComparator.sort(factories);
    this.eventListenerFactories = factories;
}
// 2. 在容器初始化单例对象结束后,遍历所有容器中bean的类
@Override
public void afterSingletonsInstantiated() {
    ConfigurableListableBeanFactory beanFactory = this.beanFactory;
    String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
    for (String beanName : beanNames) {
        Class<?> type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
        if (type != null) {
            processBean(beanName, type);
        }
    }
}

private void processBean(final String beanName, final Class<?> targetType) {
    if (!this.nonAnnotatedClasses.contains(targetType)) {
        // 2.1 通过反射解析出该类中@EventListener注解的方法
        Map<Method, EventListener> annotatedMethods = MethodIntrospector.selectMethods(targetType,
                (MethodIntrospector.MetadataLookup<EventListener>) method ->
                        AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
        if (CollectionUtils.isEmpty(annotatedMethods)) {
            this.nonAnnotatedClasses.add(targetType);
        }
        else {
            ConfigurableApplicationContext context = this.applicationContext;
            List<EventListenerFactory> factories = this.eventListenerFactories;
            for (Method method : annotatedMethods.keySet()) {
                for (EventListenerFactory factory : factories) {
                    // 3. 将这些方法通过适合的EventListenerFactory调用createApplicationListener
                    // 包装成ApplicationListener对象
                    if (factory.supportsMethod(method)) {
                        Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
                        ApplicationListener<?> applicationListener =
                                factory.createApplicationListener(beanName, targetType, methodToUse);
                        if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                            ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
                        }
                        // 3.1 注册到ApplicationContext
                        context.addApplicationListener(applicationListener);
                        break;
                    }
                }
            }
        }
    }
}           

EventListenerFactory

DefaultEventListenerFactory是默认的EventListenerFactory实现,支持所有方法。 最后将方法包装为ApplicationListenerMethodAdapter对象。

java复制代码public class DefaultEventListenerFactory implements EventListenerFactory, Ordered {
    @Override
    public int getOrder() {
        return LOWEST_PRECEDENCE;
    }

    @Override
    public boolean supportsMethod(Method method) {
        return true;
    }

    @Override
    public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
        return new ApplicationListenerMethodAdapter(beanName, type, method);
    }
}           

ApplicationListenerMethodAdatper

ApplicationListenerMethodAdapter uses the design pattern of the adapter

  1. Obtain the type of event to be listened to from the @EventListener annotation (or method parameter) of the method, as well as the conditional expression, and obtain the priority information from the @Order annotation of the method.
  2. supportsEventType 方法提供事件类型判断
  3. onApplicationEvent 方法收到事件对象时:
    1. By the parameters supported by the method (whether there are no parameters) and whether the event object is
    2. PayloadApplicationEvent 类型解析出方法调用需要的参数信息
    3. Based on the conditional expression of the annotation, determine whether the method can be called
    4. Perform a method call
    5. Publish the result of a method call as an event object
java复制代码public void processEvent(ApplicationEvent event) {
    // 通过事件对象解析方法参数
    Object[] args = resolveArguments(event);
    // 条件表达式判断
    if (shouldHandle(event, args)) {
        // 反射执行
        Object result = doInvoke(args);
        if (result != null) {
            // 将结果作为事件发布
            handleResult(result);
        }
    }
}           

summary

Spring Event uses ApplicationEventPublisher to publish events, and implements ApplicationListener to listen to events. This pattern can decouple complex business dependencies. Annotation processing functions can be used to @EventListener or @TransactionalEventListener to provide more complex condition filtering or transaction state awareness, supporting the business to achieve more complex event processing.

从源码实现方面,AbstractApplicationContext在refresh过程中初始化ApplicationEventMulticaster(SimpleApplicationEventMulticaster)和ApplicationListener,并向ApplicationEventMulticaster注册监听器。 这样在发布事件后,ApplicationEventMulticaster能够找到类型匹配的ApplicationListener,并执行调用。

For @EventListener or @TransactionalEventListener, the method handler EventListenerMethodProcessor is relied upon to iterate through all beans and find the annotated method, using the corresponding EventListenerFactory (DefaultEventListenerFactory or TransactionalEventListenerFactory). Wrap the method as an ApplicationListener. For @TransactionalEventListener, it is necessary to additionally perceive transaction state changes through the transaction synchronizer.

Author: Hima Tech Yan Zi Win

Source-WeChat public account: Himalaya technical team

Source: https://mp.weixin.qq.com/s/apDProsuz_E18w0FgSBrfg

Read on