当前位置: 首页 > 图灵资讯 > 技术篇> 与 @Named 一起揭开挑战

与 @Named 一起揭开挑战

来源:图灵教育
时间:2024-09-04 20:20:38

注入上下文和依赖注入 (cdi) 在不断发展的环境中,开发人员经常会遇到和遇到 bean 与潜在冲突相关的命名、默认实现障碍。本文进行了详细的讨论 cdi 中与 @named 注释相关潜在陷阱。本文将对其复杂性进行深入研究,明确存在问题的场景,并讨论替代方法,包括使用 smallrye 中的 @identifier。此外,我们还将提供关于构建强大和可维护的jakarta ee最佳实践见解 应用程序。

理解@default

@default 注释是 cdi 一种有价值的工具用于将特定的实现显式标记为给定接口或 bean 默认实现类型。它在处理同一接口的多个实现时发挥作用,允许开发人员在不使用其他限定符时指定默认注入哪个实现。

考虑存在 greetingservice 多个实现接口的场景:

@default
public class defaultgreetingservice implements greetingservice {

  @override
  public string greet(string name) {
    return "hello, " + name;
  }
}

public class specialgreetingservice implements greetingservice {

  @override
  public string greet(string name) {
    return "greetings, " + name + "!";
  }
}

注入不指定任何限定符的情况 bean 时,cdi 使用 @default 标记的 bean 作为默认值。这在各种实现场景中非常有用,提供了明确的默认选择。

@inject
private greetingservice greetingservice; // injects the @default implementation

虽然 @default 使用是可选的,但强烈建议使用,特别是在处理多个实现接口时。它提供了一个清晰和一致的默认选项,以防止 bean 歧义和事故发生在注入期间。

探索@named——一把双刃剑

@named 限定符在 cdi 在基本作用中发挥作用 bean 分配人类可读名称或标识符。开发人员将 bean 注入其他组件时,经常使用它通过名称引用 bean。

但是,@named 它也有自己的一系列挑战,特别是在没有额外限制符的情况下。默认情况下,cdi 将非限定类名关联为 bean 名字。这可能会导致和谐。 @default 限定符发生冲突,导致 bean 注射期间发生事故。

@named
public class mybean {
  // implementation
}

注入没有显式限定符的情况下 mybean 时,cdi 将仅添加 @named 限定符,而不是 @default 限定符。只有当在 bean 或者限制符的显式指定 @default 只有在限制符时才能应用 @default 限定符。

@inject
private mybean mybean;

在这种情况下,如果有其他具有相同类型名称的名称 bean,歧义可能会出现。例如,如果有另一个名字叫做 mybean 的 bean,注入会导致歧义。

为了解决这个问题,开发人员应该明确限制他们计划注入的内容 bean。

@inject
@named("mybean")
private mybean mybean;

或者,开发人员可以为每个人服务 bean 使用自定义限定符来消除歧义。

问题案例:含糊不清和意外违约

使用无附加限定符时 @named 有时会有歧义,同类型的实现也会有很多。考虑以下场景:

@named
public class servicea implements service {
  // implementation
}

@named
public class serviceb implements service {
  // implementation
}

注入没有显式限定符的情况下 service 因为两者可能会导致歧义 bean 根据类型匹配,并且没有名称或限定符来区分它们。

@inject
private service service;

在这种情况下,cdi 不会隐藏添加 @default 或试图解决歧义,导致注入失败,因为依赖关系不明确。

替代方案:从 smallrye common 引入 @identifier

认识到 @named 开发人员经常寻求替代方案来更清楚地控制挑战 bean 识别。其中一种替代方案来自 的 @identifier 注释 小黑麦很常见。这个注释提供了一个更清晰、更可控的注释 bean 命名方法降低了默认冲突和事故的风险。与 @named 不同,@named 要求每个应用程序都有一个独特的值,@identifier 允许多个 bean 只要它们的类型不同,具有相同的标识符值。这种灵活性在处理相同接口或相关类型的不同实现时尤为有用。

要使用@identifier,只需注释bean类并指定标识符值即可:

@identifier("payment")
public class defaultpaymentprocessor implements paymentprocessor {
  // implementation
}

@identifier("payment")
public class legacypaymentgateway implements paymentgateway {
  // implementation
}

用@identifier注入bean很简单:

public class client {
  @inject
  @identifier("payment")
  paymentprocessor processor;

  @inject
  @identifier("payment")
  paymentgateway gateway;

}

在这里,“付款”@identifier 值被多个 bean 重用,因为 paymentprocessor 和 paymentgateway 不同类型。 @named 这种灵活性是不允许的,包括 值必须是应用程序范围内唯一的值。

@named 另一种替代方法是创建自定义限定符。自定义限定符是用户定义的注释,可用于识别和限定 bean。它们提供对 bean 根据应用程序的具体需要,选择最精细的控制。

要创建自定义限制符,请按照以下步骤操作:

  1. 定义一个新的注释类。
  2. 使用@qualifier对注释类进行注释。
  3. (可选)为限定符提供默认值。

例如,以下名称 defaultpaymentgateway 自定义限定符表示默认支付网关的实现:

@qualifier
@retention(runtime)
@target({method, field, parameter, type})
public @interface defaultpaymentgateway {

}

请使用自定义限定符注释 bean 类:

@defaultpaymentgateway
public class standardpaymentgateway implements paymentgateway {
  // implementation
}

public class expresspaymentgateway implements paymentgateway {
  // implementation
}

然后注入使用限定符 bean:

@Inject
@DefaultPaymentGateway
private PaymentGateway paymentGateway;

选择正确的方法

bean 最好的识别方法取决于应用程序的具体要求。对于简单的应用程序,@named 可能就够了。对于更复杂的应用程序,@identifier 或 自定义限定符提供更多的控制和灵活性。

下表总结了各种方法的优缺点:

approach pros cons @named simple, widely supported can be ambiguous, conflicts with @default @identifier clearer identification, no conflicts with @default requires additional annotations custom qualifiers maximum flexibility, fine-grained control requires upfront effort to define and maintain

可参考官方cdi规范进一步确认

与 @Named 一起揭开挑战

结论:bean 命名和默认值的策略选择

总之,与 @named 相关潜在陷阱强调 cdi 使用此注释时需要仔细考虑。当依赖隐式命名时,特别是在多种实现的情况下,可能会出现歧义和意想不到的默认值。鼓励开发人员从smallryee等方面探索替代方案。 common@identifier,获得更多控制和更清晰的bean识别方法。采用显式限制、自定义限定符和替代方法,可以保证更流畅、更可控 cdi 体验,从而实现强健可维护的体验 java。

以上就是与 @Named 一起揭开挑战的细节,请关注图灵教育的其他相关文章!