java 事件订阅_SpringBoot事件发布与订阅

本文介绍了如何在SpringBoot中实现事件发布与订阅。通过创建自定义事件类,使用ApplicationContext发布事件,以及通过@EventListener订阅事件。还讨论了@TransactionalEventListener在事务管理中的作用和应用场景,强调了事件订阅的幂等性和重试机制的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在日常开发中,经常会遇到一个方法执行完毕,要通知另一个方法。

比如用户注册了之后需要给他发邮件。这种一个主要的业务,包含了很多附属的业务的情况,

如果对事务要求不是很严格,可以试试SpringBoot的事件发布与订阅。

事件类

首先你需要定义一个事件,这个类继承ApplicationEvent这个抽象类。

import org.springframework.context.ApplicationEvent;

/**

* 定义一个自定义事件,继承ApplicationEvent类

*

* @author lww

* @date 2020-04-09 17:41

*/

public class MyApplicationEvent extends ApplicationEvent {

private static final long serialVersionUID = 1L;

public MyApplicationEvent(Object source) {

super(source);

System.err.println("发布事件:source = " + source);

}

}

复制代码

发布事件

发布事件很简单,注入 ApplicationContext,调用 context.publishEvent(new MyApplicationEvent("发布事件啦"));就好了,这样一个事件就发布出去了。

import com.ler.eventdemo.event.MyApplicationEvent;

import javax.annotation.Resource;

import org.springframework.context.ApplicationContext;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RestController;

/**

* @author lww

* @date 2020-04-09 18:05

*/

@RestController

public class HelloController {

@Resource

private ApplicationContext context;

@GetMapping("/hello")

public String hello(String name) {

context.publishEvent(new MyApplicationEvent("发布事件啦"));

return "Hello " + name;

}

}

复制代码

3350ac40a9fe8b50ddb5b201d80a1884.png

在发布事件这里有一个小图标,点击就会跳到事件订阅的地方(在idea里)。

订阅事件

有了事件,又发布了事件,接下来就是订阅事件。也很简单,你只需要写一个listener

import com.ler.eventdemo.event.MyApplicationEvent;

import org.springframework.context.event.EventListener;

import org.springframework.stereotype.Component;

/**

* 定义一个事件监听器 MyApplicationListener

*

* @author lww

* @date 2020-04-09 17:42

*/

@Component

public class MyApplicationListener {

@EventListener

public void onApplicationEvent(MyApplicationEvent event) {

System.err.println("接收到事件:" + event.getClass());

}

}

复制代码

有的说要实现 ApplicationListener 接口,测试后发现,不需要实现什么接口。只要加@EventListener注解,然后参数指定哪个事件,就可以了。

31152818a9bf5ed595e460d6f75bb74a.png

在订阅事件这里,也有一个小图标,点击会跳到发布事件那里(在idea里)。

@TransactionalEventListener

@TransactionalEventListener 和 @EventListener差了一个 Transactional,这个事务表示的意思是,

事件的发送时机可以和事务绑定。

TransactionPhase.BEFORE_COMMIT 在提交前

TransactionPhase.AFTER_COMMIT 在提交后

TransactionPhase.AFTER_ROLLBACK 在回滚后

TransactionPhase.AFTER_COMPLETION 在事务完成后

默认 TransactionPhase.AFTER_COMMIT。

指定发布时机避免的情况就是,比如注册用户,包含了一些耗时的操作,而这些操作中有异步非阻塞的,

当执行到了发布事件的方法时。用户可能还没有创建完成,此时如果事件发布了,在监听器那边执行时,可能获取用户失败。

而如果在事务提交后执行,就不会出现这种情况。

这个注解 不是 说发布事件的方法和监听器响应方法之间有什么事务关系。他们之间还是没有事务的。无法保证原子性,一致性。

如果要实现事务也不是没有办法,可以先保证 事件的发布方执行完毕,事务提交完成。然后订阅方遵循幂等性规则,

如果订阅方失败,进入重试机制。有点像RocketMQ分段提交,事务回查与重试机制。可以按照这个思想实现。

原理

ApplicationContext 接口继承了 ApplicationEventPublisher 接口,所以有publishEvent方法,可以用于发布任务。

ApplicationListener接口继承了 EventListener接口,其中有一个onApplicationEvent方法,用来监听事件。

在org.springframework.context.support.AbstractApplicationContext#refresh方法中,

org.springframework.context.support.AbstractApplicationContext#registerListeners里面

d89f1242eb87d5623dd38ac25b0960f6.png

可以看到,注册监听器的时候是查找实现了ApplicationListener的接口,那我们没有实现,又是如何注册的呢?

369e6c602e74f8feb26fbbe4c707f682.png

@EventListener注释里有这一句,看这个类的这个方法

org.springframework.context.event.EventListenerMethodProcessor#processBean

858534c4229e73cd5704ff077bfea5f7.png

在这里,查找使用了@EventListener注解的方法,找到后同样会添加到ConfigurableApplicationContext(ApplicationContext的实现类)中,

作为listener。所以不实现ApplicationListener,同样可以正常使用。

注意的是需要使用Java配置类,如果使用xml配置,则要添加 或者

而 @TransactionalEventListener包含@EventListener

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@EventListener

public @interface TransactionalEventListener {

......

}

复制代码

@TransactionalEventListener

由 org.springframework.transaction.event.TransactionalEventListenerFactory来处理,

在这个方法中org.springframework.transaction.event.TransactionalEventListenerFactory#createApplicationListener

创建了org.springframework.transaction.event.ApplicationListenerMethodTransactionalAdapter#ApplicationListenerMethodTransactionalAdapter

在org.springframework.transaction.event.ApplicationListenerMethodTransactionalAdapter#onApplicationEvent这个方法中,使用TransactionSynchronizationEventAdapter来管理事务。

总结

SpringBoot 事件的发布订阅,使用还是非常简单方便的,在SpringBoot框架中也应用广泛,小伙伴们快快练起来吧。

本文使用 mdnice 排版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值