CDI 范围和生产商

Wil*_*ung 1 java cdi weld

有人可以解释 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");
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Nik*_*los 5

生产者方法上的CDI范围注释定义了生成的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");
}
Run Code Online (Sandbox Code Playgroud)

如果只有这两种方式,他们是可以和平共处的。当您想要注入 a 时,就会出现问题Thing,如下所示:

    @Inject
    private Thing thing;
Run Code Online (Sandbox Code Playgroud)

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

    @Inject
    private Instance<Thing> things;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

    @Inject
    @DbPassword // this is the qualifier
    private String dbPassword;
Run Code Online (Sandbox Code Playgroud)