Axon框架-事件(二)
1.什么是事件处理器

2.明确概念
- EventProcessor:事件处理器
- ProcessingGroup:处理组
- EventHandler:事件处理程序
3.事件处理器分层结构
介绍


- 事件处理程序(EventHandler):接收事件时需执行的业务逻辑
- 事件处理器(EventProcessor):则是负责处理事件处理过程中技术层面工作的组件。它会启动一个工作单元,可能还会开启事务;此外,它还需确保事件处理期间创建的所有消息能正确附加关联数据,同时满足其他非功能需求(如性能、容错等)
- 处理组(Processing Group):每个EventHandler仅属于一个处理组。处理组为事件处理提供了可配置的非功能需求能力,例如错误处理、排序策略等
为EventHandler分配ProcessingGroup
介绍
所有EventProcessor都有一个名称,该名称在多个JVM实例间唯一标识一个EventProcessor实例,两个名称相同的EventProcessor会被视为同一EventProcessor的不同实例
所有EventHandler默认会附加到名称为其类所在包名的事件处理器上。此外,Axon默认使用的EventProcessor实现是TrackingEventProcessor(跟踪式事件处理器)
EventHandler大致分为两类:常规EventHandler,Saga的EventHandler,这里介绍常规EventHandler的流程
两种分配方式

更精细的分配方式
介绍
Axon的配置API允许自定义的更精细的分配方式,这些规则可分为两大类:
- EventHandler → ProcessingGroup
- ProcessingGroup → EventProcessor

事件处理程序到处理组
- byDefaultAssignTo(String):定义EventHandler的默认ProcessingGroup名称。仅在无更具体规则且未标注@ProcessingGroup注解时生效
- byDefaultAssignHandlerInstancesTo(Function<Object, String>):通过Lambda表达式为EventHandler实例分配ProcessingGroup(返回ProcessingGroup名称)。仅在无更具体规则且未标注@ProcessingGroup注解时生效
- byDefaultAssignHandlerTypesTo(Function<Class<?>, String>):通过Lambda表达式为EventHandler类型分配ProcessingGroup(返回ProcessingGroup名称)。仅在无更具体规则且未标注@ProcessingGroup注解时生效
- assignHandlerInstancesMatching(String, Predicate<Object>):根据EventHandler实例是否匹配Predicate条件,将其分配到指定ProcessingGroup。默认优先级为0;若一个实例匹配多个条件,结果未定义
- assignHandlerTypesMatching(String, Predicate<Class<?>>):根据EventHandler类型是否匹配Predicate条件,将其分配到指定ProcessingGroup。默认优先级为0;若一个类型匹配多个条件,结果未定义
- assignHandlerInstancesMatching(String, int, Predicate<Object>):功能与第4点类似,但可自定义优先级(数值越高,规则优先级越高)
- assignHandlerTypesMatching(String, int, Predicate<Class<?>>):功能与第5点类似,但可自定义优先级(数值越高,规则优先级越高)
处理组到事件处理器
- assignProcessingGroup(String, String):将指定名称的ProcessingGroup,分配给指定名称的EventProcessor
- assignProcessingGroup(Function<String, String>):通过Lambda表达式为ProcessingGroup分配EventProcessor(输入ProcessingGroup,名称,返回EventProcessor名称)
EventProcessor内部的EventHandler顺序问题
介绍
默认顺序就是它们在配置API中的注册顺序一致
Spring环境下的显式排序
若使用Spring进行依赖注入,可通过@Order注解显式指定事件处理程序的排序。该注解标注在事件处理程序类上,通过整数参数指定优先级(数值越小,优先级越高)
java
@ProcessingGroup("my-handlers")
@Order(1) // 优先级高于 @Order(2) 的组件
public class HighPriorityHandler {
@EventHandler
public void on(ImportantEvent event) {
// 高优先级逻辑
}
}
@ProcessingGroup("my-handlers")
@Order(2) // 优先级低于 @Order(1) 的组件
public class LowPriorityHandler {
@EventHandler
public void on(ImportantEvent event) {
// 低优先级逻辑(在 HighPriorityHandler 之后执行)
}
}
注意事项

4.事件错误处理
介绍

ProcessingGroup层级(ListenerInvocationErrorHandler)
介绍
ListenerInvocationErrorHandler负责处理事件处理程序方法抛出的异常。默认实现为LoggingErrorHandler,记录异常日志后,继续处理下一个处理程序或事件

原生API配置
java
public class AxonConfig {
// 省略其他配置方法...
public void configureProcessingGroupErrorHandling(EventProcessingConfigurer processingConfigurer) {
// 1. 配置所有处理组的默认错误处理器
processingConfigurer
.registerDefaultListenerInvocationErrorHandler(conf -> {
// 示例:返回自定义 ListenerInvocationErrorHandler 实例
return (exception, event, eventHandler) -> {
// 自定义逻辑:如重试、忽略、死信队列投递等
log.error("EventHandler [{}] failed to process event [{}]",
eventHandler.getClass().getSimpleName(),
event.getPayloadType().getSimpleName(),
exception);
// 若需向上传播异常,直接抛出即可
// throw new RuntimeException("Propagate error", exception);
};
})
// 2. 为特定处理组配置专属错误处理器
.registerListenerInvocationErrorHandler("my-processing-group", conf -> {
// 为 "my-processing-group" 处理组配置自定义错误处理器
return new CustomMyGroupErrorHandler();
});
}
}
SpringBoot配置
java
@Configuration
public class AxonConfig {
// 省略其他配置方法...
@Bean
public ConfigurerModule processingGroupErrorHandlingConfigurerModule() {
return configurer -> configurer.eventProcessing(processingConfigurer ->
processingConfigurer
// 配置默认错误处理器
.registerDefaultListenerInvocationErrorHandler(conf -> {
return new LoggingErrorHandler(); // 也可使用自定义实现
})
// 为特定处理组配置错误处理器
.registerListenerInvocationErrorHandler(
"my-processing-group",
conf -> new CustomMyGroupErrorHandler()
)
);
}
}
自定义ListenerInvocationErrorHandler
实现ListenerInvocationErrorHandler接口即可自定义错误处理逻辑,接口提供以下参数:
java
public interface ListenerInvocationErrorHandler {
void onError(Exception exception,
EventMessage<?> event,
EventMessageHandler eventHandler) throws Exception;
}
- exception:EventHandler抛出的异常
- event:待处理的事件
- eventHandler:抛出异常的EventHandler
可根据需求选择重试忽略或向上传播异常;若向上传播,异常会进入EventProcessor
EventProcessor层级(ErrorHandler)
介绍
EventHandler方法外抛出的异常或从EventHandler层级传播上来的异常,由ErrorHandler处理。默认实现为PropagatingErrorHandler,直接重新抛出所有捕获的异常

不同事件处理器类型的异常传播行为
- 订阅式事件处理器(SubscribingEventProcessor):异常会传播给事件发布者
- 流处理式事件处理器(StreamingEventProcessor):进入错误模式,重试失败后暂停处理
原生API配置
java
public class AxonConfig {
public void configure(EventProcessingConfigurer configurer) {
configurer
// 1. 配置所有事件处理器的默认错误处理器
.registerDefaultErrorHandler(conf -> {
// 示例:自定义 ErrorHandler,支持重试
return new RetryingErrorHandler(
IntervalRetryScheduler.builder()
.retryCount(3)
.interval(Duration.ofSeconds(1))
.build()
);
})
// 2. 为特定事件处理器配置专属错误处理器
.registerErrorHandler("my-processor", conf -> {
return new CustomProcessorErrorHandler();
});
}
}
SpringBoot配置
java
@Configuration
public class AxonConfig {
@Bean
public ConfigurerModule processorErrorHandlingConfigurerModule() {
return configurer -> configurer.eventProcessing(processing ->
processing
// 配置全局默认错误处理器
.registerDefaultErrorHandler(conf -> new RetryingErrorHandler())
// 为特定事件处理器配置错误处理器
.registerErrorHandler("my-processor", conf -> new CustomProcessorErrorHandler())
);
}
}
自定义ErrorHandler
实现ErrorHandler接口,通过ErrorContext获取错误上下文信息,自定义处理逻辑(如忽略、重试、死信队列投递等):
java
public interface ErrorHandler {
void handleError(ErrorContext errorContext) throws Exception;
}
// 示例:自定义 ErrorHandler
public class CustomErrorHandler implements ErrorHandler {
@Override
public void handleError(ErrorContext errorContext) throws Exception {
Exception cause = errorContext.getCause();
EventMessage<?> event = errorContext.getEvent();
// 自定义逻辑:如判断异常类型,决定是否投递到死信队列
if (cause instanceof NonTransientException) {
// 非暂时性异常:投递到死信队列
deadLetterQueue.send(event, cause);
} else {
// 暂时性异常:重试
throw cause; // 向上传播,触发重试
}
}
}
死信队列
这一部分内容,还专门有一章,这里理解为一个持续失败的事件会产生不好的影响,需要死信队列来参与解决

5.EventProcessor通用配置
介绍
除了处理EventHandler分配和错误处理,EventProcessor还支持其他组件的配置。订阅式和流处理式事件处理器的专属配置以后说,这里是通用配置
EventProcessorBuilder
介绍
EventProcessingConfigurer提供了大量EventProcessor的可配置组件,但有时直接提供构建EventProcessor的完整逻辑会更便捷。此时可通过EventProcessorBuilder自定义构建逻辑

配置方式
EventProcessingConfigurer提供两种配置EventProcessorBuilder的方法:
- registerEventProcessorFactory(EventProcessorBuilder):为未配置专属构建器的EventProcessor,配置默认构建工厂
- registerEventProcessor(String, EventProcessorBuilder):为指定名称的EventProcessor,配置专属构建器
java
public class AxonConfig {
public void configureEventProcessorBuilder(EventProcessingConfigurer processingConfigurer) {
// 1. 配置默认构建器:所有未指定专属构建器的处理器使用此逻辑
processingConfigurer.registerEventProcessorFactory((name, config, invoker) -> {
// 示例:根据处理器名称,选择构建 Subscribing 或 Tracking 处理器
if (name.startsWith("subscribing-")) {
return SubscribingEventProcessor.builder()
.name(name)
.eventHandlerInvoker(invoker)
.messageSource(config.eventBus())
.build();
} else {
return TrackingEventProcessor.builder()
.name(name)
.eventHandlerInvoker(invoker)
.tokenStore(config.tokenStore())
.build();
}
});
// 2. 为 "custom-processor" 配置专属构建器
processingConfigurer.registerEventProcessor("custom-processor",
(name, config, invoker) -> new CustomEventProcessor(name, invoker, config.eventStore())
);
}
}
EventHandler拦截器
介绍
EventProcessor是EventHandler的调用者,因此也是配置EventHandler拦截器的合适位置。由于EventProcessor专门处理事件,此处的拦截器需针对EventMessage,即EventHandlerInterceptor

配置方式
EventProcessingConfigurer提供两种配置拦截器的方法:
- registerDefaultHandlerInterceptor(BiFunction<Configuration, String, MessageHandlerInterceptor<? super EventMessage<?>>>):为所有EventProcessor配置默认拦截器(输入全局配置和EventProcessor名称,返回拦截器实例)
- registerHandlerInterceptor(String, Function<Configuration, MessageHandlerInterceptor<? super EventMessage<?>>>):为指定名称的EventProcessor配置专属拦截器
java
public class AxonConfig {
public void configureInterceptors(EventProcessingConfigurer processingConfigurer) {
// 1. 配置全局默认拦截器:为所有处理器添加关联数据拦截
processingConfigurer.registerDefaultHandlerInterceptor((config, processorName) ->
new CorrelationDataInterceptor<>(config.correlationDataProviders())
);
// 2. 为 "audit-processor" 配置专属审计拦截器
processingConfigurer.registerHandlerInterceptor("audit-processor", config ->
new AuditLoggingInterceptor() // 自定义审计拦截器,记录事件处理日志
);
}
}
消息监控
介绍
所有EventProcessor实例都支持配置MessageMonitor。MessageMonitor用于监控Axon应用中消息的流转过程,对于EvnetProcessor而言,它会专门监控从EventProcessor流向EventHandler的事件

配置方式
MessageMonitorFactory是Axon配置API中通用的监控器构建接口,支持更灵活的监控器创建逻辑:
java
@FunctionalInterface
public interface MessageMonitorFactory {
// 参数说明:
// - configuration:全局配置(可获取依赖组件)
// - componentType:组件类型(事件处理器场景下为 EventProcessor 实现类)
// - componentName:组件名称(事件处理器名称)
MessageMonitor<Message<?>> create(Configuration configuration,
Class<?> componentType,
String componentName);
}
示例:
java
public class AxonConfig {
public void configureMessageMonitor(EventProcessingConfigurer processingConfigurer) {
// 使用工厂为 "metrics-processor" 配置监控器
processingConfigurer.registerMessageMonitorFactory("metrics-processor",
(config, componentType, componentName) -> {
// 示例:基于 Micrometer 实现事件处理指标监控
return MicrometerMessageMonitor.builder(componentName)
.meterRegistry(config.getComponent(MeterRegistry.class))
.build();
}
);
}
}
事务管理
介绍
EventProcessor负责事件处理,因此也是配置事务的合理位置。大多数场景下,默认配置已足够,本节仅介绍可调整的选项

TransactionManager
Axon使用TransactionManager为每个工作单元附加事务:
- Spring环境:默认使用SpringTransactionManager,底层依赖Spring的PlatformTransactionManager
- 非Spring环境:若需事务管理,需自定义TransactionManager实现,仅需实现TransactionManager#startTransaction()方法
配置方式
通过EventProcessingConfigurer的registerTransactionManager方法配置:
java
public class AxonConfig {
public void configureTransactionManager(EventProcessingConfigurer processingConfigurer) {
// 为 "transactional-processor" 配置自定义事务管理器
processingConfigurer.registerTransactionManager("transactional-processor",
config -> new CustomTransactionManager()
);
}
}
回滚配置
RollbackConfiguration用于决定工作单元何时需要回滚事务。默认配置为任何Throwable都会触发回滚,其他可选配置可参考工作单元
通过EventProcessingConfigurer的registerRollbackConfiguration方法配置:
java
public class AxonConfig {
public void configureRollback(EventProcessingConfigurer processingConfigurer) {
// 为 "custom-rollback-processor" 配置自定义回滚策略:仅 RuntimeException 触发回滚
processingConfigurer.registerRollbackConfiguration("custom-rollback-processor",
config -> RollbackConfigurationType.ANY_RUNTIME_EXCEPTION
);
}
}