首頁 > Java > java教程 > 主體

與 @Named 一起揭開挑戰

WBOY
發布: 2024-08-30 06:03:35
原創
1135 人瀏覽過

在情境和依賴注入 (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 限定符。 @Default 限定詞僅在 bean 或其限定詞上明確指定時才套用。

@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中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!