Axon框架-事件(一)
1.什么是事件
2.发布事件
介绍
在聚合内部发布事件
介绍
代码
AggregateLifecycle提供了简洁的API来实现上述需求,核心方法为静态的apply(),使用时需静态导入:
import static org.axonframework.modelling.command.AggregateLifecycle.apply;
public class GiftCard {
@AggregateIdentifier
private String id;
private int balance;
// 命令处理器:处理“发行礼品卡”命令
@CommandHandler
public GiftCard(IssueCardCommand cmd) {
// 发布“礼品卡已发行”事件,事件数据来自命令
apply(new CardIssuedEvent(cmd.getCardId(), cmd.getAmount()));
}
// 事件溯源处理器:通过事件重建聚合状态(示例)
@EventSourcingHandler
public void on(CardIssuedEvent event) {
this.id = event.getCardId();
this.balance = event.getAmount();
}
// 省略其他命令处理器、事件处理器及状态字段
}
apply方法内部机制
apply高级技巧
@CommandHandler
public void handle(RedeemCardCommand cmd) {
if (this.balance < cmd.getRedeemAmount()) {
throw new InsufficientBalanceException(id, balance, cmd.getRedeemAmount());
}
// 1. 发布“礼品卡已兑换”事件,并附加元数据(兑换门店ID)
apply(
new CardRedeemedEvent(id, cmd.getRedeemAmount()),
MetaData.with("shopId", cmd.getShopId()) // 元数据:门店ID
)
// 2. 事件发布后,执行后续逻辑(如记录兑换日志)
.andThen(() -> log.info("Card {} redeemed at shop {}", id, cmd.getShopId()))
// 3. 若余额为0,发布“礼品卡已失效”事件
.andThenApplyIf(
() -> this.balance == 0, // 条件:余额为0
() -> new CardExpiredEvent(id) // 满足条件时发布的事件
);
}
// 事件溯源处理器:处理 CardRedeemedEvent 以更新余额
@EventSourcingHandler
public void on(CardRedeemedEvent event) {
this.balance -= event.getRedeemAmount();
}
从非聚合组件中分发事件
介绍
代码
import org.axonframework.eventhandling.gateway.EventGateway;
import org.springframework.stereotype.Service;
@Service // 常规 Spring 服务组件(非聚合)
public class GiftCardNotificationService {
// 注入 EventGateway(Axon 自动配置,或手动配置)
private final EventGateway eventGateway;
// 构造函数注入
public GiftCardNotificationService(EventGateway eventGateway) {
this.eventGateway = eventGateway;
}
// 发布“礼品卡兑换通知”事件(非聚合发起)
public void sendRedeemNotification(String cardId, int amount, String userId) {
// 直接通过 EventGateway 发布事件
eventGateway.publish(
new CardRedeemNotifiedEvent(cardId, amount, userId, System.currentTimeMillis())
);
}
}
注意
- 非聚合组件发布的事件不会自动附加聚合标识符和序号(因不属于任何聚合),若需关联聚合信息,需手动在事件负载或元数据中添加
- EventGateway的publish()方法默认是异步的,若需同步等待事件发布结果,可使用publishAndWait()方法
3.处理事件
介绍
参数
第一个参数,它对应事件消息的负载。若事件处理器无需直接访问消息负载,也可在@EventHandler注解上显式指定预期的负载类型
注意:若希望将负载作为参数传入方法,则不要在@EventHandler注解上配置负载类型
匹配规则
注册
介绍
事件处理组件需通过EventProcessingConfigurer进行注册,该配置器可从全局的Axon Configurer中获取
- 通常一个应用只需定义一个EventProcessingConfiguration
- 对于大型、模块化的应用,也可为每个模块单独定义一个EventProcessingConfiguration
原生API
public class AxonConfig {
// 省略其他配置方法...
public void configureEventHandler(Configurer configurer) {
// 方式1:直接注册事件处理组件(仅处理 @EventHandler 方法)
configurer.registerEventHandler(
config -> new MyEventHandlingComponent()
);
// 方式2:注册包含多种消息处理器的组件(如同时有 @EventHandler、@CommandHandler)
configurer.registerMessageHandler(
config -> new MyEventHandlingComponent()
);
// 方式3:通过 EventProcessingConfigurer 直接注册(更显式的事件处理配置)
configurer.eventProcessing()
.registerEventHandler(config ->
new MyEventHandlingComponent()
);
}
}
SpringBoot
@Component // 纳入 Spring 上下文,Axon 会自动扫描 @EventHandler 方法
public class MyEventHandlingComponent {
@EventHandler
public void on(SomeEvent event) {
// 处理 SomeEvent 事件的业务逻辑
// 示例:更新查询模型、发送通知、触发后续命令等
}
// 可添加更多 @EventHandler 方法处理其他事件
@EventHandler
public void on(AnotherEvent event) {
// 处理 AnotherEvent 事件
}
}