CDI - Bean 名称不明确

CDI - Bean name is ambiguous

我定义了两个Bean:

@Named("mysql")
public MySqlLogService extends AbstractLogService { ... }

@Named("mysql")
public MySqlConcurrencyService implements ConcurrencyService { ... }

我认为 Named 限定符与 Bean 的类型有某种关系,但是焊接 returns:

Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001414: Bean name is ambiguous. Name mysql resolves to beans: 
  - Managed Bean [class my.package.MySqlConcurrencyService] with qualifiers [@Default @Named @Any],
  - Managed Bean [class my.other.package.MySqlLogService] with qualifiers [@Default @Named @Any]

为什么?限定符的范围是什么?

您似乎混淆了 CDI 注释。 @Named("my_custom_name") 注释用于明确引用 class/impl,例如:

@Inject
@Named("my_custom_name")
ConcurrencyService service;

如果您没有在 @Named 中定义自定义名称,那么默认情况下它会选择 class 名称,因此您不会遇到该错误。 在你的例子中:

@Named
MySqlLogService

将被称为 mySqlLogService

@Named
MySqlConcurrencyService

会被称为 mySqlConcurrencyService ,但我仍然不明白你想要达到的目标。

范围不是用 @Named 定义的,而是使用:

@RequestScoped
@SessionScoped
@ApplicationScoped
@ConversationScoped

更多信息here and here are 2 examples i ii

对于范围检查 oracle 的 page

也是一个很好的博客,解释了 Qualifiers

无论类型如何,两个启用的 bean 都不能具有相同的 bean 名称(通过 @Named)。

既然是CDI,我们看看CDI规格如何? 让我们从 2.6. Bean names 开始,它指出:

... A bean with a name may be referred to by its name when used in a non typesafe environment (like the Unified Expression Language)....

因此您可以在不参考其类型的情况下使用该 bean。因此,需要能够将 bean 名称解析为一个特定的 bean.The 用例,例如,当您从 JSF 页面使用 EL 时。

再往前一点,上面写着:

Subject to the restrictions defined in Ambiguous names, multiple beans may share the same bean name.

这允许您实际上 "break" 名称的唯一性,只要您可以保证在类型安全解析结束时,只会找到一个具有给定名称的 bean。

确保您的 bean 具有唯一的名称并且它会起作用。 如果您只需要限定符,那么使用 @Named 会带来您可能不需要的开销。只需创建您自己的限定符并从那里开始。