java ---Spring事件监听

目录

实现方式:

1.接口方式

2.注解方式

监听事件后异步执行

顺序获取事件


事件发布是 Spring 框架中最容易被忽视的功能之一,但实际上它是一个很有用的功能。使用事件机制可以将同一个应用系统内互相耦合的代码进行解耦,并且可以将事件与 Spring 事务结合起来,实现我们工作中的一些业务需求。

今天聊聊spring中的事件,帮助需要的伙伴快速上手这一模块。

事件简单理解包含三个要素:

  • 事件源:谁触发了这个事件?
  • 事件:发生了什么?
  • 事件监听器:事件发生后要做什么?

业务场景:支付之后给用户发送信息,提示支付成功

实现方式:

1.接口方式

事件类:

自定义传递的事件属性

@Getter
@Setter
@ToString
public class EmailEvent extends ApplicationEvent {

    /**
     * 事件id
     */
    private Integer id;

    /**
     * 事件数据
     */
    private Object data;

    /**
     * 事件描述
     */
    private String message;
    private final String type = "email";
    public EmailEvent(Object source) {
        super(source);
    }
    
}

监听器类:

这里要实现AppliListener这个接口

@Slf4j
@Component
public class Listener implements ApplicationListener<EmailEvent> {

    @Override
    public void onApplicationEvent(EmailEvent event) {
        log.info("监听事件成功! ");
        log.info("发送信息:用户【{}】,您已成功支付! " , event.getData());
    }

}

测试用例:

要注入ApplicationEventPublisher,用来发布事件

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

 
    @Autowired
    private ApplicationEventPublisher publisher;


    @PostMapping("/1")
    public void test(){
        //发送事件开始 
        log.info("事件1发送  " );
        EmailEvent emailEvent = new EmailEvent(this);
        emailEvent.setId(1);
        emailEvent.setMessage("支付成功!");
        emailEvent.setData("simon.wayne");
        publisher.publishEvent(emailEvent);

    }
}

输出结果:

 事件1发送  
 监听事件成功! 
 发送信息:用户【simon.wayne】,您已成功支付! 

2.注解方式

事件类:

自定义传递的事件属性

@Getter
@Setter
@ToString
public class EmailEvent extends ApplicationEvent {

    /**
     * 事件id
     */
    private Integer id;

    /**
     * 事件数据
     */
    private Object data;

    /**
     * 事件描述
     */
    private String message;
    private final String type = "email";
    public EmailEvent(Object source) {
        super(source);
    }
    
}

测试用例:

要注入ApplicationEventPublisher,用来发布事件,并通过@EventListener注解在方法上监听事件

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private ApplicationEventPublisher publisher;

    @PostMapping("/1")
    public void test(){
        //发送事件开始 
        log.info("事件1发送  " );
        EmailEvent emailEvent = new EmailEvent(this);
        emailEvent.setId(1);
        emailEvent.setMessage("支付成功!");
        emailEvent.setData("simon.wayne");
        publisher.publishEvent(emailEvent);
    }


    @EventListener
    public void accept(EmailEvent event){
        log.info("接收事件1 ,事件描述:{},事件数据:{} " , event.getMessage(),event.getData());
        log.info("发送信息:用户【{}】,您已成功支付! " , event.getData());
    }

}

输出结果:

 事件1发送  
 接收事件1事件描述:支付成功!,事件数据: simon.wayne
 发送信息:用户【simon.wayne】,您已成功支付! 

监听事件后异步执行

1.证明事件的同步性,方法发布事件,在监听器拿到事件后,执行完成才能方法才能继续执行

这里让监听器拿到事件后线程睡眠五秒钟

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

  

    @Autowired
    private ApplicationEventPublisher publisher;

    @PostMapping("/1")
    public void test(){
        //发送事件开始 2023年3月27日09:57:42
        log.info("事件1发送  " );
        EmailEvent emailEvent = new EmailEvent(this);
        emailEvent.setId(1);
        emailEvent.setMessage("支付成功!");
        emailEvent.setData("simon.wayne");
        publisher.publishEvent(emailEvent);
        log.info("方法结束!");
    }



    @EventListener
    public void accept(EmailEvent event) throws InterruptedException {
        log.info("接收事件1 ,事件描述:{},事件数据:{} " , event.getMessage(),event.getData());
        log.info("发送信息:用户【{}】,您已成功支付! " , event.getData());
        Thread.sleep(5000);
    }
}

输出结果:

事件1发送  
接收事件1 ,事件描述:支付成功!,事件数据:simon.wayne 
发送信息:用户【simon.wayne】,您已成功支付!
方法结束!

最后一行结果方法结束延迟了五秒才出现,充分证明事件是以同步的方式执行的,接下来就介绍异步执行的方法。

2.事件异步执行

方法很简单:在启动类上加一个@EnableAsync注解,启用异步功能,然后监听器方法上添加 @Async 注解即可

测试示例

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

 
    @Autowired
    private ApplicationEventPublisher publisher;

    @PostMapping("/1")
    public void test(){
        //发送事件开始 2023年3月27日09:57:42
        log.info("事件1发送  " );
        EmailEvent emailEvent = new EmailEvent(this);
        emailEvent.setId(1);
        emailEvent.setMessage("支付成功!");
        emailEvent.setData("simon.wayne");
        publisher.publishEvent(emailEvent);
        log.info("方法结束!");

    }

    @Async
    @EventListener
    public void accept(EmailEvent event) throws InterruptedException {
        Thread.sleep(5000);
        log.info("接收事件1 ,事件描述:{},事件数据:{} " , event.getMessage(),event.getData());
        log.info("发送信息:用户【{}】,您已成功支付! " , event.getData());
    }

此时的输出结果:

事件1发送  
方法结束!
接收事件1 ,事件描述:支付成功!,事件数据:simon.wayne 
发送信息:用户【simon.wayne】,您已成功支付! 

可以发现此时已是异步执行

顺序获取事件

在监听方法上加上一个@order注解,order的值越小,优先级越高

@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private ApplicationEventPublisher publisher;

    @PostMapping("/1")
    public void test(){
        //发送事件开始 2023年3月27日09:57:42
        log.info("事件1发送  " );
        EmailEvent emailEvent = new EmailEvent(this);
        emailEvent.setId(1);
        emailEvent.setMessage("支付成功!");
        emailEvent.setData("simon.wayne");
        publisher.publishEvent(emailEvent);
        log.info("方法结束!");
    }

    @Order(1)
    @EventListener
    public void sendMessage(EmailEvent event) throws InterruptedException {
        log.info("接收事件1 ,事件描述:{},事件数据:{} " , event.getMessage(),event.getData());
        log.info("发送信息:用户【{}】,您已成功支付! " , event.getData());
    }


    @Order(2)
    @EventListener
    public void deliverGoods(EmailEvent event) throws InterruptedException {
        log.info("接收事件1 ,事件描述:{},事件数据:{} " , event.getMessage(),event.getData());
        log.info("发货:用户【{}】,您的商品已发货! " , event.getData());
    }
}

输出结果:

事件1发送  
接收事件1 ,事件描述:支付成功!,事件数据:simon.wayne 
发送信息:用户【simon.wayne】,您已成功支付! 
接收事件1 ,事件描述:支付成功!,事件数据:simon.wayne 
发货:用户【simon.wayne】,您的商品已发货! 
方法结束!

可以看出 是先发送信息后发货

猜你喜欢

转载自blog.csdn.net/Smion778/article/details/130100656
今日推荐