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

Quarkus依赖注入问题:无法依据UriInfo存在性选择实现类

Quarkus依赖注入场景适配问题

我用Quarkus 2.16.3 + Kotlin搭建了如下代码结构:

interface Resolver {
    fun getInfo(): String
}

@ApplicationScoped
@Default
@Priority(1)
class ResolverNoRequest(): Resolver {
    override fun getInfo(): String {
        return "myInfo"
    }
}

@RequestScoped
@Alternative
@Priority(2)
class ResolverWithRequest(val uriInfo: UriInfo) : Resolver {
    override fun getInfo(): String {
        val hostname = uriInfo.baseUri.host
        return "myInfo with $hostname"
    }
}

注入Resolver的Consumer类:

@ApplicationScoped
class Consumer(val resolver: Resolver){
    
    fun process(){
        println(resolver.getInfo())
    }
}

预期效果

  • 请求上下文(如REST端点调用)时,注入ResolverWithRequest
  • 无请求上下文(如批处理任务)时,注入ResolverNoRequest

当前问题

多次调整注解、改用Instance<Resolver>都无法实现按上下文切换注入的逻辑。无请求上下文时,系统仍尝试注入ResolverWithRequest,因缺少UriInfo抛出错误:java.lang.IllegalStateException: No RESTEasy Reactive request in progress。目前只能用Instance<Resolver>配合try-catch的方式规避,不够优雅,希望找到Quarkus原生的正确用法。


解决方案:使用@ConditionalOnRequest注解

Quarkus提供了@ConditionalOnRequest注解,可让bean仅在请求上下文存在时生效。修改ResolverWithRequest的注解配置:

@RequestScoped
@Alternative
@Priority(2)
@ConditionalOnRequest
class ResolverWithRequest(val uriInfo: UriInfo) : Resolver {
    override fun getInfo(): String {
        val hostname = uriInfo.baseUri.host
        return "myInfo with $hostname"
    }
}

调整后,当无请求上下文时,ResolverWithRequest会被CDI忽略,自动选择ResolverNoRequest作为默认实现;在请求上下文内,由于ResolverWithRequest优先级更高,会被优先注入。Consumer类无需修改,保持原有注入方式即可。

备选方案:通过Instance筛选可用bean

如果无法使用@ConditionalOnRequest,可通过Instance遍历并筛选符合当前上下文的bean:

@ApplicationScoped
class Consumer(@Any private val resolvers: Instance<Resolver>) {

    fun process() {
        val resolver = resolvers.stream()
            .filter { bean ->
                // 请求作用域bean仅在请求上下文激活时可用
                bean.javaClass.getAnnotation(RequestScoped::class.java)?.let {
                    RequestContext.current().isActive
                } ?: true
            }
            .max(Comparator.comparingInt { bean ->
                // 按优先级排序选择最高优先级的可用bean
                bean.javaClass.getAnnotation(Priority::class.java)?.value ?: 0
            })
            .orElseThrow { IllegalStateException("未找到可用的Resolver实现") }
        
        println(resolver.getInfo())
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 22:12:10