Quarkus中方法标注@RequestScoped是否正确?是否需添加@Produces?
问题解答
一、Quarkus中为方法添加@RequestScoped注解的作用
- 标记该方法产出的Bean实例生命周期与HTTP请求绑定:每个新请求会创建一个全新的Bean实例,请求处理完成后,实例会被销毁以释放资源。
- 若该方法用于生成CDI Bean,这个作用域会直接作用在返回对象上,精准控制它的存活周期。
二、关于你的JDBI DAO实现的问题
1. 当前实现是否正确?
代码能正常运行,但存在不规范的地方:
- 按照CDI规范,生成Bean的方法必须显式添加@Produces注解,虽然Quarkus做了兼容处理,能识别这类方法为隐式生产者,但这属于Quarkus的非标准扩展,换用其他CDI容器可能无法正常工作。
- 你想要UserDAO绑定请求生命周期的意图是能实现的,但当前依赖的是Quarkus的兼容逻辑,并非标准写法,不推荐长期使用。
2. 是否需要添加@Produces注解?
一定要加,原因如下:
- 符合CDI规范,让代码在任何兼容CDI的容器中都能稳定运行,不依赖Quarkus的特殊处理。
- 明确标记该方法为Bean生产者,代码可读性更强,其他开发者能一眼理解这个方法的作用。
修改后的DAOUtils代码:
@ApplicationScoped class DAOUtils( @DataSource("user") userDataSource: AgroalDataSource ) { private val userJdbi = Jdbi.create(userDataSource) // 这里放更多JDBI配置 @Produces @RequestScoped fun userDAO(): UserDAO { return userJdbi.onDemand(UserDAO::class.java) } }
3. 如何验证Bean的创建与销毁是否正常?
有两种简单可行的验证方式:
方式一:添加生命周期回调日志
因为UserDAO是接口,JDBI会生成代理类,你可以做一个包装类,通过CDI的生命周期注解打印日志:
@RequestScoped class UserDAOWrapper(private val delegate: UserDAO) : UserDAO { @PostConstruct fun onInit() { println("UserDAO实例已创建,请求ID: ${RequestContext.current().requestId}") } @PreDestroy fun onDestroy() { println("UserDAO实例已销毁,请求ID: ${RequestContext.current().requestId}") } override fun findUser(id: Long): User { return delegate.findUser(id) } }
修改生产者方法返回这个包装类(内部持有JDBI生成的真实DAO),每次请求前后都会打印日志,能直观看到实例的创建与销毁时机。
方式二:打印实例哈希值+调试日志
- 在UserService中注入
Instance<UserDAO>,每次调用时打印实例的哈希值:
class UserService( private val userDaoInstance: Instance<UserDAO> ) { fun findUser(id: Long): User { val userDao = userDaoInstance.get() println("当前请求的UserDAO实例哈希: ${userDao.hashCode()}") return userDao.findUser(id) } }
多次发起请求,如果每次哈希值不同,说明每个请求都生成了新的实例。
- 启动Quarkus时添加
-Dquarkus.arc.debug=true参数,控制台会输出CDI Bean的创建、销毁日志,能直接查看Bean的生命周期事件。
内容的提问来源于stack exchange,提问作者Cory Skowronek
相关产品推荐
相关产品推荐

