springBoot listener ApplicationEventPublisherAware application

benefit

The listener can decouple the core business and sub business, and also facilitate the later business expansion. For example, after a new user is registered, send an email or SMS. At this time, after saving the user, publish a new user's registration success event, and realize the function of sending email or SMS by listening to this event. In the later stage, a xxx function is added for new users. At this time, a new listener listening to the registration success event can be written to process the new business logic without modifying the previous registration logic.

code

Entity class

package com.erp.payroll.evenlistener;

/**
 * @author guang
 * @version V1.0
 * @Package com.erp.payroll.evenlistener
 * @date 2021/12/1 9:36
 */
public class User {
    private Integer id;
    private String name;
    private String phoneNum;
    private String email;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPhoneNum() {
        return phoneNum;
    }
    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + ", phoneNum=" + phoneNum + ", email=" + email + "]";
    }
}

controller layer

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author guang
 * @version V1.0
 * @Package com.erp.payroll.evenlistener
 * @date 2021/12/1 9:41
 */

@RestController
@RequestMapping("/user")
public class UserRegisterController {
    @Autowired
    private UserRegisterService userRegisterService;
    @RequestMapping("/register")
    public String register(User user) {
        //Register
        userRegisterService.register(user);
        return "[controller]User registration succeeded!";

    }
}

Service layer: execute user registration and publish events

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;

/**
 * @author guang
 * @version V1.0
 * @Package com.erp.payroll.evenlistener
 * @date 2021/12/1 9:36
 */

@Service
public class UserRegisterService implements ApplicationEventPublisherAware {

    private ApplicationEventPublisher applicationEventPublisher;

    public boolean register(User user) {

        //User registration
        System.out.println("[service]user["  + user + "]Registration succeeded!");

        //News release
        applicationEventPublisher.publishEvent(new UserRegisterEvent(this, user));

        return true;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;

    }
}

Event listening: after listening to the event publishing, onApplicationEvent method will be automatically executed. Therefore, this class needs to be managed by IOC and @ Component annotation should be added to the class

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * @author guang
 * @version V1.0
 * @Package com.erp.payroll.evenlistener
 * @date 2021/12/1 9:36
 */
@Component
public class EventListener implements ApplicationListener<UserRegisterEvent> {

    @Override
    public void onApplicationEvent(UserRegisterEvent event) {

        //send emails
        System.out.println("Sending mail to: " + event.getUser().getEmail());

        //send message
        System.out.println("Texting to: " + event.getUser().getPhoneNum());
    }
}

You can use annotations
@EventListener
Used on a class to indicate that it is a listening method (unverified)

//Listening events
@EventListener
public void listenEvent(UserRegisterEvent event) {
        //send emails
        System.out.println("Sending mail to: " + event.getUser().getEmail());

        //send message
        System.out.println("Texting to: " + event.getUser().getPhoneNum());
}

Event class

import org.springframework.context.ApplicationEvent;

/**
 * @author guang
 * @version V1.0
 * @Package com.erp.payroll.evenlistener
 * @date 2021/12/1 9:36
 */
public class UserRegisterEvent extends ApplicationEvent {
    private static final long serialVersionUID = -5481658020206295565L;
    private User user;
    //Whoever publishes this event, souce is who (object)
    public UserRegisterEvent(Object source, User user) {
        super(source);
        this.user = user;
    }
    public User getUser() {
        return user;
    }
}

Execution process

The controller layer calls the registered method in the service to trigger the listening event, creates this event class (other operations can be done internally), and then publishEvent publishes the event.
Listeners listening to this event class will listen to this event with onApplicationEvent, and then execute internal methods.

Application event publisheraware event release details.

be careful

1,The listener method must be try-catch Exception, otherwise it will cause a publishing event(Transactional)Rollback using the specified method
2,have access to@Order Annotation to control the execution order of multiple listeners,@Order The smaller the value passed in, the higher the execution order
3,For transactions that need to be monitored or do not want to be monitored try-catch runtime Exception, you can use@TransactionalEventListener annotation

@TransactionalEventListener listener

If the publication of an event is not within the scope of transaction (@ Transactional), the event cannot be listened to unless the fallbackExecution flag is set to true (@ TransactionalEventListener(fallbackExecution = true)); If you are in a transaction, you can choose which phase of the transaction to listen for events. By default, you can listen after the transaction is committed.

Modify the listening transaction range:@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)

You can reopen a transaction in the listener

	@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
    public void listenEvent1(UserRegisterEvent event) {
        divide(event);
    }
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void divide(UserRegisterEvent event) {
        //send emails
        System.out.println("Sending mail to: " + event.getUser().getEmail());

        //send message
        System.out.println("Texting to: " + event.getUser().getPhoneNum());
    }

The above events are synchronous. If asynchronous is required, you need to enable asynchronous support. Just add @ Async annotation to the listener method.

Once asynchronous execution is started, method exceptions will not be thrown and can only be handled inside the method. To handle exceptions outside the method:

Async exception handling is at the end of the article.

SpringBoot publishes ApplicationEventPublisher and listens for ApplicationEvent events.

Keywords: Java

Added by Dark.Munk on Wed, 01 Dec 2021 08:35:51 +0200