Springboot-事件驱动详解

spring事件驱动组成

spring事件驱动由3个部分组成

1、ApplicationEvent:表示事件本身,自定义事件需要继承该类。用来定义事件

2、ApplicationEventPublisherAware:事件发送器,需要实现该接口。主要用来发布事件.ApplicationContext 也实现了该接口,可以用于发布事件.

Spring4.2之后,ApplicationEventPublisher自动被注入到容器中,采用Autowired即可获取。

3、ApplicationListener:事件监听器接口。监听类实现ApplicationListener 里onApplicationEvent方法即可.

在spring4.2以后我们可以以更加简洁的方式来监听event的发布,监听事件我们不必再实现ApplicationListener接口了,只要在方法上添加注解@EventListener即可.

使用步骤

Spring中使用事件非常简单,只需要以下的几个步骤:

  1. 定义事件,继承ApplicationEvent
  2. 定义监听,要么实现ApplicationListener接口,要么在方法上添加@EventListener注解
  3. 发布事件,调用ApplicationContext.publishEvent()或者ApplicationEventPublisher.publishEvent();

定义事件

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;
    }
}

发送事件:publishEvent()方法

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

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

实现观察者有2种方式

第一种方式:实现ApplicationListener接口

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

第二种方式:通过@EventListener注解,该会根据方法参数类型来自动监听相应事件的发布。

@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());
    }
}

如果要监听多个事件类型的发布,可以在@EventListener(classes = {FaceEvent.class,ArmEvent.class})指定,spring会多次调用此方法来处理多个事件。但是注意此时,方法参数不能有多个,否则会发生转换异常,可以将使用多个事件的父类作为唯一的方法参数来接收处理事件,但除非必要否则并不推荐监听多个事件的发布。

如果有多个监听器监听同一事件,我们可以在方法上使用spring的@order注解来定义多个监听器的顺序,order越小,优先级越高.

@EventListener还有一个属性,condition()里可以使用SPEL表达式来过滤监听到事件,即只有符合某种条件的才进行接收处理。比如:

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

监听多个事件:

    @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());
        }
    }

注意事项

  • 事件没要处理的监听器,就会被抛弃。
  • 一个事件可以同时被多个监听处理类监听处理。
  • 默认情况下事件是同步的,即事件被publish后会等待Listener的处理。如果发布事件处的业务存在事务,监听器处理也会在相同的事务中。
  • 如果对于事件的处理不想受到影响,可以onApplicationEvent方法上加@Async支持异步或者在有@EventListener的注解方法上加上@Async。注:启动类上同时要加上@EnableAsync

利用@TransactionalEventListener实现监听事件时的事务隔离

很多时候,只有事务提交之后我们才会发布相应的事件处理其他逻辑,比如用户注册之后,发送邮件或者短信。这时候就可以用注解@TransactionalEventListener。

@TransactionalEventListener和@EventListener都可以监听事件,但前者可以对发布事件和监听事件进行一些事务上的隔离

@TransactionalEventListener是对@EventListener的一个扩展,允许将事件的监听器绑定到事务的某个阶段。可以绑定到以下事务阶段:

  • AFTER_COMMIT (默认),事务提交后
  • AFTER_ROLLBACK ,事务回滚后
  • AFTER_COMPLETION ,事务完成,包括提交后和回滚后
  • BEFORE_COMMIT ,事务提交前

@TransactionalEventListener指不和发布事件的方法在同一个事务内,发布事件的方法事务结束后才会执行本监听方法,监听逻辑内发生异常不会回滚发布事件方法的事务

@TransactionalEventListener有一个属性为fallbackExecution,默认为false,指发布事件的方法没有事务控制时,监听器不进行监听事件,此为默认情况!fallbackExecution=true,则指发布事件的方法没有事务控制时,监听方法仍可以监听事件进行处理。

猜你喜欢

转载自blog.csdn.net/kaihuishang666/article/details/107520480