CDI 范围和生产商
CDI Scope and Producers
有人可以解释一下 CDI Scope 注释在生产者方面的作用吗?他们似乎没有完成任何事情。
@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: Ambiguous dependencies for type Thing.
Possible
dependencies:
- Producer Method [Thing] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces public
pkg.test.ThingProducer.thingMaker()],
- Producer Method [Thing] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces @RequestScoped public
pkg.test.ThingProducer.thingMakerReq()]
因此,即使 `RequestScoped 被标记为生产者方法的一部分,它们也不是限定符。
所以我只是不确定他们在生产者方法方面的作用是什么。
生产者方法上的 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的选择也没有任何作用。范围是 bean 的实现细节:假设您有一个 @ApplicationScoped
bean,然后在某个时候您意识到它需要请求级信息来实现某些功能。您可以更改它的范围,使用它的 beans 不应该在意,它们将继续工作而不会发生变化。
限定符是一种消除依赖关系歧义的方法,当类型不够时,就像你的情况一样。一个常见的例子是当有许多配置属性时,表示为字符串。假设一个 DB 用户名和密码,都是 String
类型:(警告:天真的例子,具有绑定属性的限定符会更合适,参见例如 Microprofile 配置)
@Inject
@DbUsername // this is the qualifier
private String dbUsername;
@Inject
@DbPassword // this is the qualifier
private String dbPassword;
有人可以解释一下 CDI Scope 注释在生产者方面的作用吗?他们似乎没有完成任何事情。
@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: Ambiguous dependencies for type Thing. Possible dependencies:
- Producer Method [Thing] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces public pkg.test.ThingProducer.thingMaker()],
- Producer Method [Thing] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces @RequestScoped public pkg.test.ThingProducer.thingMakerReq()]
因此,即使 `RequestScoped 被标记为生产者方法的一部分,它们也不是限定符。
所以我只是不确定他们在生产者方法方面的作用是什么。
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的选择也没有任何作用。范围是 bean 的实现细节:假设您有一个 @ApplicationScoped
bean,然后在某个时候您意识到它需要请求级信息来实现某些功能。您可以更改它的范围,使用它的 beans 不应该在意,它们将继续工作而不会发生变化。
限定符是一种消除依赖关系歧义的方法,当类型不够时,就像你的情况一样。一个常见的例子是当有许多配置属性时,表示为字符串。假设一个 DB 用户名和密码,都是 String
类型:(警告:天真的例子,具有绑定属性的限定符会更合适,参见例如 Microprofile 配置)
@Inject
@DbUsername // this is the qualifier
private String dbUsername;
@Inject
@DbPassword // this is the qualifier
private String dbPassword;