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

关于CDI中@Produces方法作用域的疑问

关于CDI中@Produces方法作用域的疑问

嗨Dalibor,我来帮你把这些CDI生产者方法的作用域问题理清楚,核心规则其实很明确,咱们一步步拆解:

1. 你当前代码的行为:方法无额外作用域注解时

你的生产者类SecurityIdentityProducer标注了@ApplicationScoped,而@Produces方法getSecurityIdentity()没有加任何作用域注解。这时候CDI会默认让这个生产者方法继承生产者类的作用域——也就是@ApplicationScoped。

简单说,这个getSecurityIdentity()只会被调用一次:第一次有注入点需要SecurityIdentity实例的时候,CDI会调用方法生成实例,之后整个应用生命周期里,所有的注入点都会复用这同一个实例。

2. 如何让每个注入点都触发方法调用?

如果你想让每一次注入都调用getSecurityIdentity()生成新实例,直接给@Produces方法加@Dependent注解就可以了——@Dependent是CDI的基础作用域,每一次注入都会创建全新的实例,完全符合“每个注入点都调用方法”的需求。

你提到的@RequestScoped是另一种情况:它会让同一个HTTP请求里的所有注入点复用同一个实例,不同请求才会重新调用方法生成新实例。如果你的需求是“每个请求一个实例”,那用@RequestScoped没问题,但如果是“每个注入点都新实例”,选@Dependent才对。

3. 注入目标Bean的作用域会影响行为吗?

答案是不会直接影响生产者方法的调用规则,生产者方法的作用域本身就决定了它生成的实例的生命周期,和注入这个实例的Bean的作用域无关。举两个例子你就懂了:

  • 如果你把@ApplicationScoped的生产者实例注入到@Singleton Bean里:Singleton Bean会持有这个全局单例的SecurityIdentity实例,一直复用;
  • 如果你把@RequestScoped的生产者实例注入到@Singleton Bean里:CDI会自动生成一个代理对象注入到Singleton里,这个代理会在每次调用时,自动指向当前请求的SecurityIdentity实例(因为Singleton是全局的,没法直接持有请求级的实例,代理是CDI的适配手段);
  • 不管你注入到@Singleton还是@Stateless Bean,生产者方法的作用域规则都是生效的,不会因为目标Bean的类型改变调用频率。

快速总结

  • 全局单例复用实例:保持现有代码(生产者类@ApplicationScoped,方法无注解)
  • 每个请求复用一个实例:给@Produces方法加@RequestScoped
  • 每个注入点都生成新实例:给@Produces方法加@Dependent

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 06:59:31