You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus中Kotlin@ApplicationScoped类init块多次执行的问题求助

Quarkus + Kotlin 初始化逻辑重复执行问题解决

当前方式的问题

你用@Startup+@ApplicationScoped配合Kotlininit块的方式不正确,原因是Quarkus的@ApplicationScoped bean默认采用客户端代理模式:Kotlin的init块属于类初始化逻辑,会在代理类加载初始化时执行一次,再在实际bean实例创建时执行一次,最终导致初始化代码被执行两次。

推荐解决方案

1. 使用@PostConstruct替代init块

将初始化逻辑移到标注@PostConstruct的方法中,这是CDI标准注解,只会在bean实例真正初始化完成后执行一次,不受代理机制影响。

示例代码:

import jakarta.enterprise.context.ApplicationScoped
import jakarta.annotation.PostConstruct
import io.quarkus.runtime.Startup

@Startup
@ApplicationScoped
class Initializer {

    @PostConstruct
    fun initVariables() {
        println("Init Variables")
        // 编写你的初始化逻辑
    }
}

2. 监听Quarkus StartupEvent

通过监听应用启动事件来执行初始化,这种方式完全避开CDI代理的影响,确保只执行一次,且不需要额外的@Startup注解(监听StartupEvent本身会触发启动时执行)。

示例代码:

import jakarta.enterprise.context.ApplicationScoped
import jakarta.enterprise.event.Observes
import io.quarkus.runtime.StartupEvent

@ApplicationScoped
class Initializer {

    fun handleStartup(@Observes event: StartupEvent) {
        println("Init Variables")
        // 编写你的初始化逻辑
    }
}

3. 关闭bean的代理模式(不推荐除非特殊场景)

给@ApplicationScoped添加proxy = false参数,关闭代理模式,这样init块只会在bean实例创建时执行一次。但要注意:如果该bean需要通过接口注入到其他组件中,关闭代理会导致注入失败,仅适合直接通过类注入的场景。

示例代码:

import jakarta.enterprise.context.ApplicationScoped
import io.quarkus.runtime.Startup

@Startup
@ApplicationScoped(proxy = false)
class Initializer {

    init {
        println("Init Variables")
        // 编写你的初始化逻辑
    }
}

总结

优先使用@PostConstruct或StartupEvent监听的方式,这两种都是Quarkus和CDI的标准用法,稳定性更高,不会出现重复执行的问题。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 23:07:22