The use of ApplicationListener in Spring

Background

  • The ApplicationContext event mechanism is the implementation of the Observer design pattern. ApplicationContext event processing can be implemented through the ApplicationEvent class and ApplicationListener interface;
  • If there is an ApplicationListener bean in the container, when the ApplicationContext calls the publishEvent method, the corresponding bean will be triggered.

spring built-in events

Built-in events Description
ContextRefreshedEvent This event is triggered when the ApplicationContext is initialized or refreshed. This can also happen using the refresh() method in the ConfigurableApplicationContext interface. Initialization here means: all beans are successfully loaded, post-processing beans are detected and activated, all Singleton beans are pre-instantiated, and the ApplicationContext container is ready and available
< strong>ContextStartedEvent This event is published when the ApplicationContext is started using the start() method in the ConfigurableApplicationContext (ApplicationContext sub-interface) interface. You can investigate your database, or you can restart any stopped applications after receiving this event.
ContextStoppedEvent This event is published when the ApplicationContext is stopped using stop() in the ConfigurableApplicationContext interface. You can do the necessary cleanup work after receiving this event.
ContextClosedEvent This event is published when the ApplicationContext is closed using the close() method in the ConfigurableApplicationContext interface. A closed context reaches the end of its life cycle; it cannot be refreshed or restarted.
RequestHandledEvent This is a web-specific event that tells all beans that the HTTP request has been served. Can only be applied to web applications using DispatcherServlet. When using Spring as the front-end MVC controller, the system will automatically trigger this event after Spring finishes processing the user request.

Likewise, events can be customized, monitored, and processed completely according to your own business logic.

ApplicationListener source code

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

    /**
     * Handle an application event.
     * @param event the event to respond to
     */
    void onApplicationEvent(E event);

}

ContextRefreshedEvent event monitoring

Taking Spring’s built-in event ContextRefreshedEvent as an example, when the ApplicationContext is initialized or refreshed, the ContextRefreshedEvent event will be triggered. Next, we will implement an ApplicationListener to monitor the occurrence of this event.

@Component
public class MyListener implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("Number of initialized beans in the container:" + event.getApplicationContext().getBeanDefinitionCount());
    }

}

Start the service and you can see

At this point, the implementation and instantiation of an event and listening class have been completed.

Customize events and monitoring, take sending emails as an example

  • Custom email notification event class: EmailEvent
package com.lw.coodytest.event;

import org.springframework.context.ApplicationEvent;

/**
 * @Classname EmailEvent
 * @Description Email notification event
 * @Author lw
 * @Date 2019-12-20 11:05
 */
public class EmailEvent extends ApplicationEvent {

    private String email;

    private String content;

    public EmailEvent(Object source){
        super(source);
    }

    public EmailEvent(Object source, String email, String content){
        super(source);
        this.email = email;
        this.content = content;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}
  • Custom email notification listening class: EmailListener
package com.lw.coodytest.listener;

import com.lw.coodytest.event.EmailEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * @Classname EmailListener
 * @Description Email notification listening
 * @Author lw
 * @Date 2019-12-20 11:10
 */
@Component
public class EmailListener implements ApplicationListener<EmailEvent> {

    @Override
    public void onApplicationEvent(EmailEvent emailEvent) {
        System.out.println("Email address:" + emailEvent.getEmail());
        System.out.println("Email content:" + emailEvent.getContent());
    }

}
  • Unit test class
package com.lw.coodytest.junit;

import com.lw.coodytest.event.EmailEvent;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.context.WebApplicationContext;

/**
 * @Classname ListenerTest
 * @Description Listening test class
 * @Author lw
 * @Date 2019-12-20 11:12
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class ListenerTest {

    @Autowired
    private WebApplicationContext webapplicationcontext;

    @Test
    public void testListener(){
        EmailEvent emailEvent = new EmailEvent("object", "[email protected]", "###listener");
        webapplicationcontext.publishEvent(emailEvent);
    }

}

The listener is instantiated through the @Component annotation and prints relevant information in onApplicationEvent

  • Executing the test class, you can see

At this point, the implementation and instantiation of a custom event and listening class have been completed.

pay attention:

Whether it is built-in listening or external custom listening, the class that implements ApplicationListener must be defined as a bean, which can be annotated with @Component or Define it in bean.xml to implement.