【问题标题】:Inject a @RequestScoped bean twice as different instances将 @RequestScoped bean 作为不同实例注入两次
【发布时间】:2020-07-02 09:16:41
【问题描述】:

我有以下情况(Java EE、CDI、jax.rs):

我有一个 RequestScoped Bean,它存储了请求的实时使用的一些数据:

MyHandler.java:
@RequestScoped
public class MyHandler
{
    ....
}

然后我有我的 REST 调用,它使用我的 Handler Bean 的两个 不同 实例:

MyRestCall.java:
@Stateless
public class MyRestCall
{
    @Inject
    MyHandler handlerA;

    @Inject
    MyHandler handlerB;

    ....
}

然而,发生的事情是,hanlderAhandlerB 是同一个对象。但我想要两个不同的。我怎样才能以适当的方式实现这一目标?当然,我可以创建一个基类 Handler,然后派生出两个单独的类 HandlerAHandlerB 并将它们@Inject 作为 handlerA 和 handlerB。但我希望有一种更清洁的方式。

【问题讨论】:

    标签: java jakarta-ee


    【解决方案1】:

    这个 bean 是请求范围,所以在请求生命周期的所有处理过程中,应该只有一个这样的 bean。你不应该期望得到一个新的。

    具有这种行为的范围是@Dependent 范围。你有没有想过用它来做那个豆子?每次你注入它时它都会产生新的 bean,所以它看起来是一个更好的解决方案。当然,在您使用相同 bean 的其他地方,将会注入新的。

    【讨论】:

    • 简短而准确!非常感谢!像魅力一样工作。
    【解决方案2】:

    尝试使用Instance注解@New

    @Inject
    @New(MyHandler.class)
    Instance<MyHandler> handlerInstanceA;
    
    @Inject
    @New(MyHandler.class)
    Instance<MyHandler> handlerInstanceB;
    

    然后使用以下方法获取您的实例:

    MyHandler handlerA = handlerInstanceA.get();
    MyHandler handlerB = handlerInstanceB.get();
    

    更新

    documentation 表示 @New 在 CDI 1.1 中已弃用,而应使用 @Dependent 范围:

    New 限定符在 CDI 1.1 中已弃用。鼓励 CDI 应用程序改为注入 Dependent 范围 bean。

    所以使用:

    @Inject
    MyHandler handlerA;
    
    @Inject
    MyHandler handlerB;
    

    由于 @Dependent 是默认的 CDI 范围,因此您的 MyHandler 不带注释或使用 @Dependent 注释:

    @Dependent
    public class MyHandler {...}
    

    根据@Dependentdocumentation

    使用范围 @Dependent 声明的 Bean 与具有其他内置范围类型的 Bean 的行为不同。当一个bean被声明为具有@Dependent的范围时:

    • 没有注入的 bean 实例在多个注入点之间共享。
    • 注入到由容器创建的对象中的任何bean 实例都绑定到新创建对象的生命周期。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-02
      • 2019-08-04
      • 1970-01-01
      • 2016-06-08
      • 2015-07-14
      • 2016-05-15
      • 2016-12-04
      相关资源
      最近更新 更多