【Spring】事件发布与@EventListener

在这里插入图片描述

前言

在Spring框架中,事件(Event)是一种实现应用程序不同组件之间解耦和通信的机制。Spring事件模型基于观察者设计模式,允许发布者(publisher)发送事件,而不需要知道哪些订阅者(subscriber)会接收这些事件。

关键知识点:

ApplicationEvent:这是所有Spring事件的基础类,自定义事件通常会扩展这个类。

ApplicationListener:任何希望接收特定类型事件的对象都需要实现这个接口。当一个事件被发布时,所有注册为该事件类型的监听器都会被通知。

ApplicationContext:Spring应用上下文实现了ApplicationEventPublisher接口,可以用来发布事件,当上下文接收到发布事件的请求时,它会将事件传递给所有注册为该事件类型的监听器。

ApplicationEventMulticaster:这是实际负责将事件广播给所有相关监听器的组件,默认的实现是SimpleApplicationEventMulticaster,但也可以配置其他实现以支持不同的广播策略,如异步处理或按顺序处理。

事件发布:发布事件通常通过调用ApplicationEventPublisherpublishEvent方法完成,该方法接受一个ApplicationEvent对象作为参数。

事件监听:要监听事件,需要创建一个类实现ApplicationListener接口,并覆盖其onApplicationEvent方法。在这个方法中,可以处理具体的事件逻辑。

注解驱动的事件监听:从Spring 4.2开始,可以通过@EventListener注解来简化事件监听器的实现。只需在方法上添加这个注解,并指定要监听的事件类型,Spring就会自动注册这个方法作为监听器。

异步事件处理:Spring支持异步处理事件,可以通过配置ApplicationEventMulticaster来启用。这通常用于避免长时间运行的事件处理阻塞主线程。

特定类型的事件:除了基础的ApplicationEvent外,Spring还提供了许多预定义的事件类型,如ContextRefreshedEvent(上下文刷新事件)、ContextStartedEvent(上下文启动事件)、ContextStoppedEvent(上下文停止事件)和ContextClosedEvent(上下文关闭事件)等。

通过使用事件机制,Spring应用程序能够以松散耦合的方式进行通信,使得各组件之间的依赖关系更加灵活,也更容易进行维护和扩展。

文件结构

在这里插入图片描述

实现

MainApplication

MainApplication.java

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@EnableAsync
@SpringBootApplication
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

common.OrderCreateEvent

OrderCreateEvent.java

package org.example.common;

import lombok.Data;
import org.springframework.context.ApplicationEvent;

/**
 * 我们要操作的对象
 */
@Data
public class OrderCreateEvent extends ApplicationEvent {

    public Object log;

    /**
     * @param log    需要传递的参数
     * @param source 事件源对象
     */
    public OrderCreateEvent(Object source, Object log) {
        super(source);
        this.log = log;
    }
}

common.OrderEvent

OrderEvent.java

package org.example.common;

import lombok.Data;
import org.springframework.context.ApplicationEvent;

/**
 * 我们要操作的对象
 */
@Data
public class OrderEvent extends ApplicationEvent {

    public Object log;

    private Integer status;

    private Integer exists = 0;

    private Integer async = 0;

    /**
     * @param log    需要传递的参数
     * @param source 事件源对象
     */
    public OrderEvent(Object source, Object log) {
        super(source);
        this.log = log;
    }
}

controller.HelloController

HelloController.java

package org.example.controller;

import org.example.service.OrderService;

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

import java.io.IOException;


@RestController
public class HelloController {

    @Autowired
    private OrderService orderService;

    @PostMapping("/event-publish")
    public void eventPublish() {
        orderService.submit();
    }

    @PostMapping("/event-publish2")
    public void eventPublish2() {
        orderService.submit2();
    }

    @PostMapping("/event-publish3")
    public void eventPublish3() {
        orderService.submit3();
    }

    @PostMapping("/event-publish4")
    public void eventPublish4() {
        orderService.submit4();
    }
}


service.OrderService

OrderService.java

package org.example.service;

import lombok.extern.slf4j.Slf4j;
import org.example.common.OrderCreateEvent;
import org.example.common.OrderEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class OrderService {

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    /**
     * 订单提交
     */
    public void submit() {
        log.info("提交订单前....");
        
        OrderCreateEvent orderCreateEvent = new OrderCreateEvent(this, "创建订单");
        // 发布事件
        applicationEventPublisher.publishEvent(orderCreateEvent);
        
        log.info("提交订单后....");
    }


    public void submit2() {
        log.info("提交订单前....");
        
        OrderEvent orderEvent = new OrderEvent(this, "提交订单事件2");
        orderEvent.setStatus(1);
        // 发布事件
        applicationEventPublisher.publishEvent(orderEvent);
        
        log.info("提交订单后....");
    }

    public void submit3() {
        log.info("提交订单前....");
        
        OrderEvent orderEvent = new OrderEvent(this, "提交订单事件3");
        orderEvent.setStatus(1);
        orderEvent.setExists(1);
        // 发布事件
        applicationEventPublisher.publishEvent(orderEvent);
        
        log.info("提交订单后....");
    }

    public void submit4() {
        log.info("提交订单前....");
        
        OrderEvent orderEvent = new OrderEvent(this, "提交订单事件4");
        orderEvent.setAsync(1);
        // 发布事件
        applicationEventPublisher.publishEvent(orderEvent);
        
        log.info("提交订单后....");
    }
}

service.OrderLogService

OrderLogService.java

package org.example.service;

import lombok.extern.slf4j.Slf4j;
import org.example.common.OrderCreateEvent;
import org.example.common.OrderEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.event.TransactionalEventListener;

@Service
@Slf4j
public class OrderLogService {

    /**
     * 条件事件监听
     * @param OrderCreateEvent orderCreateEvent
     */
    @EventListener(classes = {OrderCreateEvent.class})
    public void listen(OrderCreateEvent orderCreateEvent) {
        log.info("事件监听:{}", orderCreateEvent.getLog());
        try {
            // 验证事件的同步
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 条件事件监听2
     * @param OrderEvent event
     */
    @EventListener(condition = "#event.status == 1 && #event.exists == 0")
    public void listen2(OrderEvent event) {
        log.info("事件监听:{}, event.status = {}", event.getLog(), event.getStatus());
        try {
            // 验证事件的同步
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 条件事件监听3
     * @param OrderEvent event
     */
    @EventListener(condition = "#event.status == 1 && #event.exists == 1")
    public void listen3(OrderEvent event) {
        log.info("事件监听:{}, event.status = {}, event.exist = {}", event.getLog(), event.getStatus(), event.getExists());
        try {
            // 验证事件的同步
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 异步事件监听
     * @param event
     */
    @Async
    @EventListener(condition = "#event.async == 1")
    public void listen4(OrderEvent event) {
        try {
            // 验证事件的异步
            Thread.sleep(5000);
            log.info("异步事件监听:{}", event.getLog());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果

POST http://localhost:8080/event-publish

在这里插入图片描述

POST http://localhost:8080/event-publish2

在这里插入图片描述

POST http://localhost:8080/event-publish3

在这里插入图片描述

POST http://localhost:8080/event-publish4

在这里插入图片描述

总结

事件机制可以将同一个应用系统内互相耦合的代码进行解耦,并且可以将事件与 Spring 事务结合起来,实现我们工作中的一些业务需求。本文结合案例讲述了事件的基本的用法。

参考

https://blog.csdn.net/mu_se_yao_rao/article/details/119610130?ops_request_misc=%257B

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锥栗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值