Spring events

Introduction

In this article we will explain how to use events in Spring.

To use events in Spring, some rules need to be followed:

  • Define the event in one of two ways
    • inherited fromApplicationEvent
    • does not inherit fromApplicationEvent
  • Define the event publisher in one of two ways
    • inject an ApplicationEventPublisherobject into the event publisher
    • The event publisher implements the interfaceApplicationEventPublisherAware
  • Implement event listeners in one of two ways
    • implement interfaceApplicationListener
    • use annotations@EventListener

custom event

Spring allows the creation and publication of custom events, and by default, the execution of the processing logic for these events is synchronous . This has some advantages, for example, the event processing logic in the listener can participate in the transaction context of the event publisher.

A simple application event

Let's create a simple event class that just carries the source object information and a message.

Method 1: Inherit fromApplicationEvent

import org.springframework.context.ApplicationEvent;
public class CustomApplicationEvent extends ApplicationEvent {
    private String message;

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

    public String getMessage() {
        return message;
    }
}

Method 2: Do not inherit fromApplicationEvent

public class CustomEvent {
    private String message;
    Object source;

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

    public String getMessage() {
        return message;
    }
}

event publisher

Now let's create a publisher for the above event. The event publisher constructs the event object and publishes the event.

To publish an event, a publisher can simply inject ApplicationEventPublisherand then call its event publishing API method publishEvent():

public class CustomSpringEventPublisher {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    /**
     * 发布两个事件:
     * 1. 继承自 Spring ApplicationEvent 的事件
     * 2. 不继承自 Spring ApplicationEvent  的任意Java对象事件
     *
     * @param message 事件中所要携带的消息
     */
    public void publishEvent(final String message) {
        System.out.println("Publishing custom ApplicationEvent . ");
        CustomApplicationEvent customApplicationEvent = 
            new CustomApplicationEvent(this, message);
        applicationEventPublisher.publishEvent(customApplicationEvent);//发布事件

        System.out.println("Publishing custom common event . ");
        CustomEvent customEvent = new CustomEvent(this, message);
        applicationEventPublisher.publishEvent(customEvent);//发布事件
    }
}

In addition to the above method, there is another method that the publisher class implements ApplicationEventPublisherAwarethe interface. If the interface is implemented, the event publisher will be injected into the event publisher bean when the application starts ApplicationEventPublisher. Usually, however, @Autowireit is easier to inject event publishers with annotations.

event listener

Finally let's create the event listener.

ApplicationEventsubclass event listener

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;

// 该例子中提到的两种监听方法可以分开独立使用,相互之间并无关系,
// 本例子将它们放在同一类中仅仅出于演示其监听同一类型事件的目的
@Component
public class CustomApplicationEventListener 
        implements ApplicationListener<CustomApplicationEvent> {
    // 监听方法一:监听器类继承自ApplicationListener
    @Override
    public void onApplicationEvent(CustomApplicationEvent event) {
        System.out.println(
                "ApplicationListener -- Received custom spring ApplicationEvent - "
                + event.getMessage());
    }
    // 监听方法二:使用注解@EventListener
    @EventListener
    public void handleCustomApplicationEvent(CustomApplicationEvent event) {
        System.out.println(
                "@EventListener -- Received custom spring ApplicationEvent - "
                + event.getMessage());
    }
}

Note that our custom event listener takes the custom event's generic type as a parameter, which makes the event listener method onApplicationEvent()type safe. It also avoids onApplicationEvent()checking whether the input parameter is a given event type and the corresponding type conversion in .

nonApplicationEvent -subclassed event listeners

import org.springframework.context.ApplicationListener;
import org.springframework.context.PayloadApplicationEvent;
import org.springframework.context.event.EventListener;

// 该例子中提到的两种监听方法可以分开独立使用,相互之间并无关系,
// 本例子将它们放在同一类中仅仅出于演示其监听同一类型事件的目的
@Component
public class CustomEventListener 
        implements ApplicationListener<PayloadApplicationEvent<CustomEvent>> {
    // 监听方法一:监听器类继承自ApplicationListener
    @Override
    public void onApplicationEvent(PayloadApplicationEvent<CustomEvent> event) {
        System.out.println("ApplicationListener -- Received custom common event - "
                + event.getPayload().getMessage());
    }

    // 监听方法二:使用注解@EventListener
    @EventListener
    public void handleCustomEvent(CustomEvent event) {
        System.out.println("@EventListener -- Received custom common event - "
                + event.getMessage());
    }
}

One thing to be reminded about in the above example is that if the defined class of the published event is Tnot inherited from ApplicationEvent, then it will be internally packaged as an PayloadApplicationEvent<T>object and then published, but only the listener whose method onApplicationEventparameter is PayloadApplicationEvent<T>can listen to the event.

In addition, again, by default, Spring events are executed synchronously, and the method of the event publisher publishEvent()will block until all listeners have finished processing the published event (actually synchronous execution in the same thread).

Create asynchronous events

In some cases, synchronous processing is not really what we need, we want to be asynchronous.

There are two ways to do it asynchronously:

Specify the asynchronous task executor to the event publisher in the configuration file

You can TaskExecutorcreate one using a taskexecutor( ) in your configuration ApplicationEventMulticaster; our example uses a class SimpleAsyncTaskExecutorto demonstrate this:

@Configuration
public class AsynchronousSpringEventsConfig {
    @Bean(name = "applicationEventMulticaster")
    public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
        SimpleApplicationEventMulticaster eventMulticaster 
          = new SimpleApplicationEventMulticaster();

        eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
        return eventMulticaster;
    }
}

Now, the event, event publisher, and listener implementations remain the same as before, but the event handling logic in the listener already handles the event in a separate thread.

Asynchronously annotated event listener methods

    @Async
    @EventListener
    public void handleCustomSpringEvent(CustomApplicationEvent event) {
       System.out.println("Received spring custom event - " + event.getMessage());
    }

Framework built-in events

Spring itself originally publishes various events. For example, ApplicationContextvarious frame events such as ContextRefreshedEvent, ContextStartedEvent, etc. are published RequestHandledEvent.

These events provide an opportunity for application developers to participate in the application and context life cycle, and developers can add some custom logic where needed.

Here is an example of an event listener listening for application context refreshes:

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

@Component
public class ContextRefreshedListener 
  implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent cse) {
        System.out.println("Handling context refreshed event. ");
    }
}

Summarize

This article mainly describes the event mechanism of the Spring framework itself. In addition to using the Spring framework's own event mechanism, developers can actually use other third-party event mechanisms, such as the Guava event bus .

In addition, the source code of the examples mentioned in this article can be found on github .

Reference article

Spring Events
Better application events in Spring Framework 4.2
Spring 4.3 – Event Listener
Spring事件机制

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325591510&siteId=291194637