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
相关产品推荐
相关产品推荐

