首页 Java java教程 与 @Named 一起揭开挑战

与 @Named 一起揭开挑战

Aug 30, 2024 am 06:03 AM

在上下文和依赖注入 (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 不允许这种灵活性,其中
值在应用程序范围内必须是唯一的。

Another alternative to @Named is to create custom qualifiers. Custom qualifiers are user-defined annotations that can be used to identify and qualify beans. They offer the most granular control over bean selection and can be tailored to specific needs of the application.

To create a custom qualifier, follow these steps:

  1. Define a new annotation class.
  2. Annotate the annotation class with @Qualifier.
  3. Optionally, provide a default value for the qualifier.

For example, the following custom qualifier named DefaultPaymentGateway indicates the default payment gateway implementation:

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface DefaultPaymentGateway {

}
登录后复制

To use the custom qualifier, annotate the bean class with it:

@DefaultPaymentGateway
public class StandardPaymentGateway implements PaymentGateway {
  // Implementation
}
登录后复制
public class ExpressPaymentGateway implements PaymentGateway {
  // Implementation
}
登录后复制

Then, inject the bean using the qualifier:

@Inject
@DefaultPaymentGateway
private PaymentGateway paymentGateway;
登录后复制

Choosing the Right Approach

The best approach for bean identification depends on the specific needs of the application. For simple applications, @Named may be sufficient. For more complex applications, @Identifier or
custom qualifiers offer more control and flexibility.

The following table summarizes the pros and cons of each approach:

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

For further confirmation, you can refer to the official CDI specification

Unveiling Challenges with @Named

Conclusion: Strategic Choices for Bean Naming and Defaults

In conclusion, the potential pitfalls associated with @Named underscore the need for careful consideration when using this annotation in CDI. Ambiguity and unintended defaults can arise when relying on implicit naming, especially in the presence of multiple implementations. Developers are encouraged to explore alternatives such as @Identifier from SmallRye Common for a more controlled and explicit approach to bean identification. Embracing explicit qualification, custom qualifiers, and alternative approaches ensures a smoother and more controlled CDI experience, leading to robust and maintainable Java.

以上是与 @Named 一起揭开挑战的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1653
14
CakePHP 教程
1413
52
Laravel 教程
1306
25
PHP教程
1251
29
C# 教程
1224
24
公司安全软件导致应用无法运行?如何排查和解决? 公司安全软件导致应用无法运行?如何排查和解决? Apr 19, 2025 pm 04:51 PM

公司安全软件导致部分应用无法正常运行的排查与解决方法许多公司为了保障内部网络安全,会部署安全软件。...

如何将姓名转换为数字以实现排序并保持群组中的一致性? 如何将姓名转换为数字以实现排序并保持群组中的一致性? Apr 19, 2025 pm 11:30 PM

将姓名转换为数字以实现排序的解决方案在许多应用场景中,用户可能需要在群组中进行排序,尤其是在一个用...

如何优雅地获取实体类变量名构建数据库查询条件? 如何优雅地获取实体类变量名构建数据库查询条件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架进行数据库操作时,经常需要根据实体类的属性名构造查询条件。如果每次都手动...

如何使用MapStruct简化系统对接中的字段映射问题? 如何使用MapStruct简化系统对接中的字段映射问题? Apr 19, 2025 pm 06:21 PM

系统对接中的字段映射处理在进行系统对接时,常常会遇到一个棘手的问题:如何将A系统的接口字段有效地映�...

IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本启动Spring...

Java对象如何安全地转换为数组? Java对象如何安全地转换为数组? Apr 19, 2025 pm 11:33 PM

Java对象与数组的转换:深入探讨强制类型转换的风险与正确方法很多Java初学者会遇到将一个对象转换成数组的�...

电商平台SKU和SPU数据库设计:如何兼顾用户自定义属性和无属性商品? 电商平台SKU和SPU数据库设计:如何兼顾用户自定义属性和无属性商品? Apr 19, 2025 pm 11:27 PM

电商平台SKU和SPU表设计详解本文将探讨电商平台中SKU和SPU的数据库设计问题,特别是如何处理用户自定义销售属...

如何利用Redis缓存方案高效实现产品排行榜列表的需求? 如何利用Redis缓存方案高效实现产品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis缓存方案如何实现产品排行榜列表的需求?在开发过程中,我们常常需要处理排行榜的需求,例如展示一个�...

See all articles