与 @Named 一起揭开挑战
在上下文和依赖注入 (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:
- Define a new annotation class.
- Annotate the annotation class with @Qualifier.
- 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
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中文网其他相关文章!

热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

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

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

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

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

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

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

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

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

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

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