ApplicationEvent&ApplicationListener使用

Use ApplicationEvent&ApplicationListener to complete business decoupling in SpringBoot

 

Foreword:

   In the project, the coupling between the various business logics is often strong, because we directly refer to the associated service or jpa in the service as the collaborative processing logic. However, this method greatly improves the difficulty of later updating and maintenance. Coupling can be minimized by using event notification and event monitoring to process logic.

 

Event listener implementation in spring   

ApplicationEvent and ApplicationListener are an implementation of event monitoring and subscription provided by Spring. The internal implementation principle is the observer design pattern. The original intention of the design is also to decouple the business logic of the system and improve scalability and maintainability. The event publisher does not need to consider who is listening, what is the specific implementation content of the monitoring, and the publisher's job is only to publish the event.   

 

Below we use ApplicationEvent and ApplicationListener to complete a simple user registration, and an example of sending an email after successful registration.

 

1. Before starting our example, let's define a User object

public class User implements java.io.Serializable{

    

    private static final long serialVersionUID = 110406535439289650L;

    private String username;

    private String password;

 

//Omit get/set method

}

 

2. Create UserRegisterEvent

 

   Define a user registration event, and listeners are suspended around the event.

 

public class UserRegisterEvent extends ApplicationEvent{

    

    private static final long serialVersionUID = -2493647928101170759L;

    

    //register user event

    private User user;

    

    //override the constructor

    public UserRegisterEvent(Object source,User user) {

        super(source);

        this.user = user;

    }

 

    public User getUser() {

        return user;

    }

 

    public void setUser(User user) {

        this.user = user;

    }

}

 

Our custom event UserRegisterEvent inherits ApplicationEvent. After inheritance, the constructor must be overloaded. The parameters of the constructor can be specified arbitrarily. The source parameter refers to the object where the event occurred. Generally, we use the this keyword instead of this keyword when publishing the event. Class object, and the user parameter is our custom registered user object, which can be obtained in the listener.

 

3. Create UserService

Add a registerUser method to the UserService class, which implements the registration event publishing function

 

@Service

public class UserService {

    

    @Autowired

    private ApplicationContext applicationContext;

    

    public void registerUser(User user){

//publish registration event      

        applicationContext.publishEvent(new UserRegisterEvent(this, user));

    }

}

 

Event publishing is controlled by the ApplicationContext object. Before publishing the event, we need to inject the ApplicationContext object and call the publishEvent method to complete the event publishing.

 

4. Create UserController

Create a @RestController controller, corresponding to adding a registration method for simple implementation

 

@RestController

public class UserController {

 

    @Autowired

    private UserService userService;

    

    @RequestMapping("/user/register")

    public String registerUser(){

        

        User user = new User();

        user.setPassword("12346");

        user.setUsername("admin");

        //Call the registration business logic

        userService.registerUser(user);

        

        return "success";

    }

}

 

5. Listen to the UserRegisterEvent event

   There are many ways to implement monitoring in Spring, such as: @EventListener annotation, implementation of ApplicationListener generic interface, implementation of SmartApplicationListener interface, etc. Let's explain how to implement these three methods respectively.

 

6. @EventListener implementation

   

@Component

public class AnnotationRegisterListener {

 

@EventListener

public void userRegister(UserRegisterEvent registerEvent){

System.out.println("The registered user information is as follows: "+registerEvent.getUser());

}

 

@EventListener

public void userRegisterEmail(UserRegisterEvent registerEvent){

System.out.println("User registration is successful"+registerEvent.getUser().getUsername()+", send email");

}

}

 

We only need to let our listener class be managed by Spring, and add the @EventListener annotation to our user registration listener implementation method, which will complete the listener according to the events configured in the method. Next, we start the project to test whether our event is perceived by the listener when it is published.

 

    test event listener

 

The browser accesses http://localhost:8080/user/register, calls the interface to register the user, and the output information is as follows:

 

The registered user information is as follows: User [username=admin, password=12346]

    User registration is successful admin, send email

 

It can be seen that the listener configured with the @EventListener annotation has taken effect. When we publish the registration event in the UserService, the listener method is automatically called and the internal information is output to the console.

 

7. ApplicationListener implements monitoring

   When implementing the ApplicationListener interface, you need to pass the listening event as a generic, and listen to the implementation code

   

    @Component

public class RegisterApplicationListener implements ApplicationListener<UserRegisterEvent>{

 

@Override

public void onApplicationEvent(UserRegisterEvent event) {

System.out.println("User registration information is as follows:"+event.getUser());

}

}

 

@Component

public class RegisterEmailApplicationListener implements ApplicationListener<UserRegisterEvent>{

 

@Override

public void onApplicationEvent(UserRegisterEvent event) {

System.out.println("User registration is successful, send email");

}

}

 

After we implement the interface, we need to use the @Component annotation to declare that the listener needs to be injected and managed by Spring. When a UserRegisterEvent event is published, the listener will automatically call the onApplicationEvent method and pass the UserRegisterEvent object as a parameter.

 

The test is successful, the same as step 6 test

 

8. SmartApplicationListener implements monitoring

   When multiple listeners listen to the same event, the monitoring is out of order, and the order of the monitored events appears completely randomly. The order of the listening logic can be realized through SmartApplicationListener.

   

    @Component

public class RegisterSmartApplicationListener implements SmartApplicationListener{

 

//Monitoring will only be performed when supportsEventType and supportsSourceType return to true

@Override

public void onApplicationEvent(ApplicationEvent event) {

 

System.out.println("User registration information is as follows:"+((UserRegisterEvent)event).getUser());

}

/**

* Event listening order in case of synchronization

* @see org.springframework.core.Ordered#getOrder()

*/

@Override

public int getOrder() {

//The smaller the value, the higher the priority and the higher the execution

return 0;

}

 

@Override

public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {

 

return eventType == UserRegisterEvent.class;

}

 

@Override

public boolean supportsSourceType(Class<?> sourceType) {

return sourceType == UserService.class;

}

}

       

@Component

public class RegisterEmainSmartApplicationListener implements SmartApplicationListener{

 

//Monitoring will only be performed when supportsEventType and supportsSourceType return to true

@Override

public void onApplicationEvent(ApplicationEvent event) {

System.out.println("User registered successfully, send email"+((UserRegisterEvent)event).getUser());

}

 

/**

* Event listening order in case of synchronization

* @see org.springframework.core.Ordered#getOrder()

*/

@Override

public int getOrder() {

//The smaller the value, the higher the priority, the earlier the execution, and the email will be sent after the user has successfully registered

return 1;

}

 

@Override

public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {

 

return eventType == UserRegisterEvent.class;

}

 

@Override

public boolean supportsSourceType(Class<?> sourceType) {

return sourceType == UserService.class;

}

}   

 

Through the getOrder method provided by SmartApplicationListener, this method can realize the ordering of monitoring. The smaller the value of return, the higher the priority and the higher the execution order.

 

The test is the same as the test in step 6

 

9. Use @Async to implement asynchronous listening

@Aysnc is actually a component in Spring that can complete asynchronous calls to single or multiple methods in a class, which can greatly save waiting time. The internal implementation mechanism is the thread pool task ThreadPoolTaskExecutor, which executes the method or class configured with @Async through the thread pool.

 

Configure the thread pool as follows:

 

@Configuration

@EnableAsync

public class AsyncConfig {

@Bean

public AsyncTaskExecutor getAsyncExecutor() {

ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();

threadPool.setCorePoolSize(2);//Number of current threads

threadPool.setMaxPoolSize(50);// maximum number of threads

threadPool.setQueueCapacity(100);//Buffer queue used by thread pool

threadPool.setWaitForTasksToCompleteOnShutdown(true);//Wait for the task to complete when shutting down -- indicating waiting for all threads to finish executing

threadPool.setThreadNamePrefix("provider-demo-");

threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

return threadPool;

}

}

 

Use @Async to implement asynchronous monitoring, and add Async annotations to the specific monitoring method onApplicationEvent. The usage is the same as adding Async annotations to ordinary methods.

@Override

    @Async

    public void onApplicationEvent(ApplicationEvent applicationEvent) {

       

        System.out.println("User registration is successful, send email notification.");

    }

 

 

Note: If there are multiple listeners for the same event, and there are asynchronous and synchronous coexistence, there is no execution order.

Guess you like

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