# SpringBoot Event 事件同步、异步处理

SpringBoot Event事件同步、异步处理

  • 业务需求场景:按照一定的顺序做一些事情,例如向A表插入数据事物提交之后,向B表中插入历史记录,最后向C表插入。
事件机制

事件监听机制可以理解为是一种观察者模式,有数据发布者(事件源)和数据接受者(监听器);在Java中,事件对象都是继承java.util.EventObject对象,事件监听器都是java.util.EventListener实例;Spring中

Java事件
  • EventObject

java.util.EventObject是事件状态对象的基类,它封装了事件源对象以及和事件相关的信息。所有java的事件类都需要继承该类。

  • EventListener

java.util.EventListener是一个标记接口,就是说该接口内是没有任何方法的。所有事件监听器都需要实现该接口。事件监听器注册在事件源上,当事件源的属性或状态改变的时候,调用相应监听器内的回调方法。

  • Source

事件源不需要实现或继承任何接口或类,它是事件最初发生的地方。因为事件源需要注册事件监听器,所以事件源内需要有相应的盛放事件监听器的容器。

Spring 事件

在 Spring 中,初始化容器时会调用 org.springframework.context.ConfigurableApplicationContext 接口中的 reFresh() 方法进行 Bean的加载,该方法会进行事件的监听注册。

代码实例
  • UserEvent:user事件对象,继承ApplicationEvent
public class UserEvent<T> extends ApplicationEvent {

    private T data;

    public UserEvent(T source) {
        super(source);
        this.data =source;
    }

    public T getData() {
        return this.data;
    }

    public void setData(final T data) {
        this.data = data;
    }
}

  • 发布插入用户的事件
@Autowired
private ApplicationEventPublisher publisher;

/**
  * 发布插入user表的事件
  */
private void sendInsertUser() {
    User user = new User();
    user.setId(20210317);
    user.setUsername("测试张三");
    UserEvent<User> userEvent = new UserEvent<>(user);
    // 发布事件
    publisher.publishEvent(userEvent);

}
  • 插入用户监听器:同步操作
/**
* 监听插入User的事件
*/
@EventListener
public void insertUserLinster(UserEvent<User> userEvent) {
	User data = userEvent.getData();
	String message = String.format("get user message: %s", JSON.toJSONString(data));
	log.info(message);
	// 后续操作;继续处理
}
  • 测试代码:
/**
  * SpringBoot Event 使用
  *
  * @return
  */
@Override
public BackResult testEvent() {
    BackResult backResult = new BackResult();
    try {
        // 向user 表插入数据
        insertUsers();
        // 添加user插入对象操作
        sendInsertUser();
        backResult.setSuccess(true);
        backResult.setMessage("操作成功!");
    } catch (Exception e) {
        backResult.setMessage(e.getMessage());
        backResult.setSuccess(false);
    }
    return backResult;
}
  • insertUsers:开启事务
/**
  * 插入开启事物
  */
@Transactional(rollbackFor = Exception.class)
public void insertUsers() {
    insertUserBatch();
}
思考

测试代码中,方法执行顺序应该是insertUsers()执行完成,事务提交之后在执行sendInsertUser(),所以事件监听器因该改进一下,在事务提交之后去执行。改进代码如下。

  • 插入用户监听器:
/**
  * 监听插入User的事件 : 在上个事务提交之后在执行
  */
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT,fallbackExecution = true)
public void insertUserLinster(UserEvent<User> userEvent) {
	User data = userEvent.getData();
	String message = String.format("get user message: %s", JSON.toJSONString(data));
	log.info(message);
	// 后续操作;继续处理
}

还有一个问题就是没有考虑,同步和异步的问题,上面的方式是同步的,这样会影响正常的业务逻辑,为了不影响正常的业务操作,可以将监听器修改为异步执行的即可。使用 @Async 标记即可,注意前提条件是:使用 @EnableAsync 开启 Spring 异步。

/**
  * 监听插入User的事件 : 在上个事务提交之后在执行
  */
@Async
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT,fallbackExecution = true)
public void insertUserLinster(UserEvent<User> userEvent) {
    User data = userEvent.getData();
    String message = String.format("get user message: %s", JSON.toJSONString(data));
    log.info(message);
    // 后续操作;继续处理
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot中,可以使用事件机制来实现异步事件处理异步事件可以在应用程序中的不同组件之间进行通信,以实现解耦和并发处理。 要使用Spring Boot的事件机制,首先需要定义一个事件类,该类表示要发布的事件事件类可以是普通的POJO类,通常包含一些必要的属性和方法。 然后,需要定义一个事件监听器类,该类用于处理特定类型的事件。监听器类需要实现`ApplicationListener`接口,并通过泛型指定要监听的事件类型。在监听器类中,可以定义一个或多个处理事件的方法。 接下来,需要在应用程序中触发事件。可以通过使用`ApplicationEventPublisher`接口中的`publishEvent()`方法来发布事件。该接口可以通过自动装配的方式注入到需要触发事件的组件中。 最后,当触发事件时,监听器类中相应的方法将被调用来处理事件。如果希望异步处理事件,可以在监听器类中使用`@Async`注解来标记处理方法,以便在单独的线程中执行。 以下是一个简单的示例代码,演示了如何在Spring Boot中实现异步事件处理: ```java // 定义事件类 public class MyEvent extends ApplicationEvent { private String message; public MyEvent(Object source, String message) { super(source); this.message = message; } public String getMessage() { return message; } } // 定义事件监听器类 @Component public class MyEventListener implements ApplicationListener<MyEvent> { @Async @Override public void onApplicationEvent(MyEvent event) { System.out.println("Received event: " + event.getMessage()); // 处理事件逻辑 } } // 触发事件的组件 @Component public class EventTriggerComponent { @Autowired private ApplicationEventPublisher eventPublisher; public void triggerEvent(String message) { MyEvent event = new MyEvent(this, message); eventPublisher.publishEvent(event); } } ``` 在上述示例中,`MyEvent`表示自定义的事件类,`MyEventListener`是事件监听器类,`EventTriggerComponent`是触发事件的组件。 当调用`EventTriggerComponent`的`triggerEvent()`方法时,会发布一个`MyEvent`事件,然后`MyEventListener`中的`onApplicationEvent()`方法将被异步调用来处理事件。 需要注意的是,为了让Spring Boot支持异步事件处理,还需要在配置类中添加`@EnableAsync`注解。 这就是使用Spring Boot实现异步事件处理的基本步骤。通过事件机制,可以方便地在应用程序中实现解耦和并发处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

全栈程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值