You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Kotlin中Axon事件处理器与查询处理器无法协同工作问题

问题分析与解决建议

先来看你提供的代码示例:

@Component
open class UserProjectionQuery {
    @Autowired
    private lateinit var repository: UserDocumentRepository
    @Autowired
    private lateinit var updateEmitter: QueryUpdateEmitter

    @QueryHandler
    fun handle(query: QueryUserIdForUsername): String? {
        //stuff
    }

    @EventHandler
    fun on(evt: UserAuthenticated) {
        //stuff
    }
}

问题核心

你遇到的情况很典型:当一个类同时包含@QueryHandler@EventHandler方法时,Spring仅生成了AnnotationQueryHandlerAdapter,却没有生成对应的AnnotationEventHandlerAdapter,最终导致repositoryupdateEmitter无法完成注入。更奇怪的是相同写法在Java中完全正常,这确实很可能和Spring与Kotlin的兼容逻辑有关。

可能的原因

  1. Kotlin类的open特性与注解扫描的冲突:虽然你手动给类加了open关键字,但Spring对Kotlin类中混合CQRS注解的处理逻辑和Java有差异——Java类默认支持继承,而Kotlin需要显式声明,注解扫描器可能没正确识别两类注解方法的共存。
  2. 字段注入的初始化顺序问题:你用的是@Autowired字段注入+lateinit的组合,这种方式在Spring处理多类型适配器时,容易因为初始化顺序紊乱导致依赖无法注入。
  3. 依赖版本兼容问题:如果你的Axon(从注解来看应该是用了Axon框架)、Spring Boot和Kotlin版本不匹配,也可能触发这类注解处理的Bug。

解决方案建议

1. 切换到构造注入(最推荐)

Kotlin的构造注入语法简洁,而且Spring会优先处理构造注入的依赖,能完美规避字段注入的初始化顺序问题,代码改造后如下:

@Component
class UserProjectionQuery(
    private val repository: UserDocumentRepository,
    private val updateEmitter: QueryUpdateEmitter
) {

    @QueryHandler
    fun handle(query: QueryUserIdForUsername): String? {
        //stuff
    }

    @EventHandler
    fun on(evt: UserAuthenticated) {
        //stuff
    }
}

如果你的项目启用了kotlin-spring插件,它会自动把Spring组件类标记为open,所以不需要手动加open关键字。

2. 检查并升级依赖版本

确认你的Spring Boot、Kotlin以及Axon框架的版本是否为最新稳定版,很多这类注解扫描的Bug都会在新版本中被修复。

3. 确认Kotlin插件配置

确保你的构建脚本中正确引入了kotlin-spring插件,它能帮助Spring更好地识别和处理Kotlin类:

// build.gradle.kts示例
plugins {
    id("org.springframework.boot") version "x.x.x"
    id("io.spring.dependency-management") version "x.x.x"
    kotlin("jvm") version "x.x.x"
    kotlin("plugin.spring") version "x.x.x" // 这个插件是关键
}

4. 临时方案优化(拆分类)

如果上述方法都无效,你当前采用的拆分类方案是可行的——把@QueryHandler@EventHandler方法分别放到不同的@Component类中,这种方式能彻底规避混合注解的扫描问题。

总结

优先尝试构造注入的改造,这是最优雅且能解决大部分依赖注入问题的方案;如果还是不行,再考虑升级依赖或拆分类。这类问题本质上是Spring对Kotlin混合注解方法的扫描逻辑缺陷,调整注入方式或依赖版本通常能解决。

内容的提问来源于stack exchange,提问作者PolishCivil

火山引擎 最新活动