Springboot-event driven detailed explanation

spring event-driven composition

The spring event drive consists of 3 parts

1. ApplicationEvent: indicates the event itself, custom events need to inherit this class. Used to define events

2. ApplicationEventPublisherAware: Event sender, need to implement this interface. Mainly used to publish events. ApplicationContext also implements this interface, which can be used to publish events.

After Spring 4.2, ApplicationEventPublisher is automatically injected into the container and can be obtained using Autowired.

3. ApplicationListener: event listener interface. The listener class can implement the onApplicationEvent method in ApplicationListener.

After spring 4.2, we can monitor the release of events in a more concise way. To monitor events, we no longer need to implement the ApplicationListener interface, just add the annotation @EventListener to the method.

Steps for usage

Using events in Spring is very simple, only the following steps are required:

  1. Define events, inherit ApplicationEvent
  2. To define the listener, either implement the ApplicationListener interface or add @EventListener annotation to the method
  3. To publish an event, call ApplicationContext.publishEvent() or ApplicationEventPublisher.publishEvent();

Define event

public class OrderCreateEvent extends ApplicationEvent {
    
    

    private final Order order;

    public OrderCreateEvent(Object source, Order order) {
    
    
        super(source);
        this.order = order;
    }

    public Order getOrder() {
    
    
        return order;
    }
}

Send event: publishEvent() method

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void save(Order order) {
    
    
        //生成订单号
        String orderNo = getOrderNo();
        order.setOrderNo(orderNo);
        log.info("订单保存成功:" + order);
        //发布订单创建事件
        applicationEventPublisher.publishEvent(new OrderCreateEvent(this, order));
    }

There are 2 ways to realize the observer

The first way: implement the ApplicationListener interface

@Component
public class OrderCreateEventListener implements ApplicationListener<OrderCreateEvent> {
    
    
    @Override
    public void onApplicationEvent(OrderCreateEvent event) {
    
    
        System.out.printf("实现ApplicationListener接口,监听OrderCreateEvent事件");
    }
}

The second way: through @EventListener annotation, it will automatically monitor the release of the corresponding event according to the method parameter type.

@Component
@Slf4j
public class OrderCreateEventListener3 {

    @EventListener (classes = {OrderCreateEvent.class}) //classes属性指定处理事件的类型
    @Async //异步监听
    @Order(0)//使用order指定顺序,越小优先级越高
    public void eventListener(OrderCreateEvent event) {
        log.info("通过注解@EventListener和@Async,异步监听OrderCreateEvent事件,orderId:" + event.getOrder().getOrderNo());
    }
}

If you want to monitor the release of multiple event types, you can specify it in @EventListener(classes = {FaceEvent.class,ArmEvent.class}). Spring will call this method multiple times to handle multiple events. But note that at this time, there cannot be multiple method parameters, otherwise a conversion exception will occur. You can use the parent class of multiple events as the only method parameter to receive and process events, but it is not recommended to monitor the release of multiple events unless necessary .

If there are multiple listeners listening to the same event, we can use spring's @order annotation on the method to define the order of multiple listeners. The smaller the order, the higher the priority.

@EventListener also has an attribute. SPEL expressions can be used in condition() to filter and listen to events, that is, only those that meet a certain condition will receive processing. such as:

@EventListener(condition = "event.message == 'message'")

Monitor multiple events:

    @EventListener({
    
    FaceEvent.class,ArmEvent.class})
    public void onApplicationEvent3(Object event) {
    
    

        if(event instanceof FaceEvent){
    
    
            LOGGER.info("===> B 收到人脸事件:  {}",((FaceEvent) event).getEventData());
        }else if(event instanceof ArmEvent){
    
    
            ArmEvent armEvent = (ArmEvent) event;
            LOGGER.info("===> B 收到臂膀事件:  {}",armEvent.getEventData());
        }
    }

Precautions

  • Listeners that are not handled by the event will be discarded.
  • An event can be monitored and processed by multiple monitor processing classes at the same time.
  • By default, the event is synchronous, that is, after the event is published, it will wait for the Listener to process it. If there is a transaction in the business where the event is posted, the listener processing will also be in the same transaction.
  • If you don't want to be affected by event processing, you can add @Async to the onApplicationEvent method to support asynchronous or add @Async to the annotation method with @EventListener. Note: @EnableAsync must be added to the startup class at the same time

Use @TransactionalEventListener to achieve transaction isolation when monitoring events

In many cases, we will publish the corresponding event processing other logic only after the transaction is submitted, such as sending emails or SMS after the user registers. At this time, you can use the annotation @TransactionalEventListener.

Both @TransactionalEventListener and @EventListener can monitor events, but the former can perform some transactional isolation on publishing events and listening events .

@TransactionalEventListener is an extension of @EventListener, allowing event listeners to be bound to a certain stage of the transaction. Can be bound to the following transaction phases:

  • AFTER_COMMIT (default), after the transaction is committed
  • AFTER_ROLLBACK, after the transaction is rolled back
  • AFTER_COMPLETION, the transaction is completed, including after commit and rollback
  • BEFORE_COMMIT, before the transaction is committed

@TransactionalEventListener means that it is not in the same transaction as the method that publishes the event. The method that publishes the event will only execute this monitoring method after the transaction ends . An exception in the listening logic will not roll back the transaction of the publishing event method .

@TransactionalEventListener has an attribute of fallbackExecution, the default is false , which means that when the method of publishing events has no transaction control, the listener does not listen to the event, this is the default situation! fallbackExecution=true, it means that when the method of publishing the event has no transaction control, the listening method can still listen to the event for processing.

Guess you like

Origin blog.csdn.net/kaihuishang666/article/details/107520480