【问题标题】:CDI Scope and ProducersCDI 范围和生产者
【发布时间】:2021-06-04 18:33:21
【问题描述】:

有人可以解释 CDI 范围注释在生产者方面的作用吗?他们似乎什么也没做。

@Produces
public Thing thingMaker() {
    System.out.println("Making thingmaker");
    return new ThingBean("thingMaker");
}

@Produces
@RequestScoped
public Thing thingMakerReq() {
    System.out.println("Making thingmakerReq");
    return new ThingBean("thingMakerReq");
}

这些自然会在启动时给出这个(省略的)错误。

WELD-001409:Thing 类型的依赖关系不明确。 可能的 依赖:

  • 生产者方法 [Thing] 带有限定符 [@Any @Default] 声明为 [[BackedAnnotatedMethod] @Produces public pkg.test.ThingProducer.thingMaker()],
  • 带有限定符 [@Any @Default] 的生产者方法 [Thing] 声明为 [[BackedAnnotatedMethod] @Produces @RequestScoped public pkg.test.ThingProducer.thingMakerReq()]

因此,即使 `RequestScoped 被标记为生产者方法的一部分,它们也不是限定符。

所以我只是不确定他们在生产者方法方面的作用。

【问题讨论】:

    标签: java cdi weld


    【解决方案1】:

    CDI scope 生产者方法上的注释定义了 produced bean 的范围;所以:

    @Produces // produces Thing in the default scope, i.e. @Dependent
    public Thing thingMaker() {
        System.out.println("Making thingmaker");
        return new ThingBean("thingMaker");
    }
    
    @Produces // produces Thing in request scope
    @RequestScoped
    public Thing thingMakerReq() {
        System.out.println("Making thingmakerReq");
        return new ThingBean("thingMakerReq");
    }
    

    如果只有这两种方法,他们就能和平共处。当你想注入一个Thing时,问题就出现了:

        @Inject
        private Thing thing;
    

    CDI 搜索其命名空间并找到多个可以满足此注入点的 bean;不知道该怎么做,它失败了(在 Weld 是 CDI 实现的特定情况下,使用 WELD-001409)。例如,以下内容是完全合法的:

        @Inject
        private Instance<Thing> things;
    

    Instance 可以为您提供满足注入点的 bean 集合,您可以选择其中任何一个来使用。

    现在,限定符是另一回事,它与 CDI 如何找到满足注入点的 bean 有关。

    首先,消除误解:范围注释不是限定符。您可以注意到在 CDI 的消息中,“with qualifiers [@Any @Default] declared as [[... @RequestScoped ...]”。这也意味着您不能从注入点中的特定范围请求 bean。并且包含注入点的bean的范围对注入bean的选择也没有任何作用。 Scope 是 bean 的一个实现细节:假设您有一个 @ApplicationScoped bean,然后在某些时候您意识到它需要请求级别的信息来实现某些功能。您可以更改其范围,使用它的 bean 不必在意,它们将继续工作而无需更改。

    限定符是一种消除依赖关系的方法,当类型不够时,就像你的情况一样。一个常见的例子是当有许多配置属性时,表示为字符串。假设一个 DB 用户名和密码,类型均为 String:(警告:天真示例,具有绑定属性的限定符会更合适,参见例如 Microprofile 配置)

        @Inject
        @DbUsername // this is the qualifier
        private String dbUsername;
    
        @Inject
        @DbPassword // this is the qualifier
        private String dbPassword;
    

    【讨论】:

    猜你喜欢
    • 2022-10-12
    • 2013-09-17
    • 2023-03-29
    • 2015-04-08
    • 1970-01-01
    • 2017-09-04
    • 2015-09-09
    • 2016-02-25
    • 1970-01-01
    相关资源
    最近更新 更多