Tao
Tao

Spring Events User Guide

Spring Events Usage Guide

Spring events are a mechanism in the Spring framework for implementing an event notification system based on the publish-subscribe pattern within an application. We can use Spring events to achieve simple business decoupling. This article will introduce the usage of Spring Events and related examples based on the SpringFramework 5.3.32 version.

In Spring, events are implemented through the following core components:

  1. Event:
  • An event represents a certain state or operation in the application.
  • In Spring, an event is typically a Java object, which can be a predefined Spring event type (such as a subclass of ApplicationEvent), or a custom event type.
  1. Event Publisher:
  • The event publisher is responsible for publishing events.
  • In Spring, the ApplicationEventPublisher interface can be used to publish events.
  • Typically, the event publisher is implemented by components within the Spring container, which can be Spring Beans or other components.
  1. Event Listener:
  • The event listener is responsible for subscribing to and handling events.
  • In Spring, the ApplicationListener interface or annotations (such as @EventListener) can be used to define event listeners.
  • Listeners can be registered with the event publisher to receive notifications for specific types of events.
Event Description
ContextRefreshedEvent Published when the ApplicationContext is initialized or refreshed. This event indicates that the ApplicationContext has loaded all Beans, activated post-processor Beans, instantiated all singleton Beans, and is ready to be used. As long as the context is not closed, it can be refreshed multiple times, provided that the chosen ApplicationContext actually supports such “hot” refreshing (e.g., XmlWebApplicationContext supports hot refreshing, but GenericApplicationContext does not).
ContextStartedEvent Published when the ApplicationContext is started via the start() method of the ConfigurableApplicationContext interface. “Started” here means that all Lifecycle Beans have received an explicit start signal. Typically, this signal is used to re-start Beans after an explicit stop, but it can also be used to start components that have not been configured for auto-start at initialization time.
ContextStoppedEvent Published when the ApplicationContext is stopped via the stop() method of the ConfigurableApplicationContext interface. “Stopped” here means that all Lifecycle Beans have received an explicit stop signal. A stopped context can be restarted via the start() method.
ContextClosedEvent Published when the ApplicationContext is closed via the close() method of the ConfigurableApplicationContext interface or the JVM’s shutdown hook. “Closed” here means that all singleton Beans will be destroyed. Once the context is closed, it has reached the end of its lifecycle and cannot be refreshed or restarted.
RequestHandledEvent A web-specific event that notifies all Beans that an HTTP request has been handled. This event is published after the request is completed. This event is only applicable to web applications using Spring’s DispatcherServlet.
ServletRequestHandledEvent A subclass of RequestHandledEvent that provides Servlet-specific context information. It includes additional details related to the Servlet request handling.

Extend the ApplicationEvent class and override the constructor.

Example:

java

/**
 * Implement the corresponding constructor based on the actual situation.
 */
import org.springframework.context.ApplicationEvent;
public class CustomEvent extends ApplicationEvent {
    private String message;
    public CustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
}

There are two ways to implement a custom event listener:

  • Implement the ApplicationListener interface and specify the generic type.
  • Use the @EventListener annotation.

java

import org.springframework.context.ApplicationListener;
public class CustomEventListener implements ApplicationListener<CustomEvent> {
    @Override
    public void onApplicationEvent(CustomEvent event) {
        System.out.println("Received custom event with message: " + event.getMessage());
    }
}

If the listener is implemented without annotations, register it with the Spring container using:

  • ApplicationContext.addApplicationListener

java

 public class SpringEventDemo {
  public static void main(String[] args) {
  AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
  ConfigurableApplicationContext applicationContext = (ConfigurableApplicationContext) context;
  applicationContext.addApplicationListener(new ApplicationListener<ApplicationEvent>() {
  @Override
  public void onApplicationEvent(ApplicationEvent event) {
  println("Received event: " + event);
  }
  });
  context.register(SpringEventDemo.class);
  context.register(MyListener.class);
  //Start the container and refresh
  context.refresh();
  //Publish the start event
  context.start();
  //Close the container
  context.close();
  }
}
  • Register as a Spring Bean

java

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class DemoApplication {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.registerBean(EventPublisher.class);
        context.registerBean(CustomEventListener.class);
        context.refresh();
        EventPublisher eventPublisher = context.getBean(EventPublisher.class);
        eventPublisher.publishEvent("Hello, Spring Event!");
        context.close();
    }
}

There are two ways to publish an event:

  • Use the ApplicationEventPublisher class
  • Use the ApplicationEventMulticaster

Both methods essentially use the ApplicationEventMulticaster to publish the event.

Example code:

java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
public class EventPublisher {
    private final ApplicationEventPublisher eventPublisher;
    @Autowired
    public EventPublisher(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }
    public void publishEvent(String message) {
        CustomEvent event = new CustomEvent(this, message);
        eventPublisher.publishEvent(event);
    }
}

Through the event mechanism provided by the Spring container, when an event is published, all registered listeners for the corresponding event type will be notified and execute the corresponding operations. This mechanism allows different modules in the application to communicate and interact in a loosely coupled manner, improving code maintainability and extensibility.

Typical use cases for Spring events include:

  • Notifying other modules to perform corresponding tasks after triggering an operation in the application.
  • Notifying other modules to process accordingly when a certain state changes in the application.
  • Triggering corresponding events when performing logging, monitoring, or metrics operations in the application.

In summary, the Spring event mechanism provides a flexible, loosely coupled way for components to communicate. Through event publishing and listening, different modules can be effectively decoupled, enabling more efficient application design and development. Related code can be found on GitHub.

Related Content