SeamFramework.orgCommunity Documentation
我們已經看過了 Web Bean 的依賴注入模型如何讓我們在建置時置換(override)了一個 API 的實做。比方說,下列企業級的 Web Bean 在生產時提供了 PaymentProcessor
這個 API 的一個實做:
@CreditCard @Stateless
public class CreditCardPaymentProcessor
implements PaymentProcessor {
...
}
不過在我們的中繼環境(staging environment)中,我們利用了不同的 Web Bean 來置換了 PaymentProcessor
的實做:
@CreditCard @Stateless @Staging
public class StagingCreditCardPaymentProcessor
implements PaymentProcessor {
...
}
我們嘗試要對 StagingCreditCardPaymentProcessor
進行的就是在系統的某個特定的 deployment 中完全地替換掉 AsyncPaymentProcessor
。在該 deployment 中,@Staging
這個 deployment type 將會擁有比 @Production
這個預設 deployment type 還要高的優先權,因此含有下列注入點的客戶端:
@CreditCard PaymentProcessor ccpp
將會收到 StagingCreditCardPaymentProcessor
的一個 instance。
不過我們有幾點需要小心:
優先權較高的 Web Bean 無法實做它所嘗試置換的 Web Bean 的所有 API 類型、
優先權較高的 Web Bean 無法宣告它所嘗試置換的 Web Bean 的所有綁定類型、
優先權較高的 Web Bean 無法擁有與它所嘗試置換的 Web Bean 相同的名稱,或是
它所嘗試置換的 Web Bean 可能能夠宣告一個 producer method、disposal method 或是 observer method。
在各個情況下,我們所嘗試置換的 Web Bean 都還是可能在 runtime 時被調用。因此,置換可能會造成開發上的錯誤。
Web Bean 提供了一項特殊的功能稱為 specialization,它可協助開發人員避免發生這些錯誤。Specialization 一開始看起來似乎有些難懂,不過實際上卻相當易於使用,並且您將會慶幸擁有它所提供的額外安全性。
Specialization 是一項基於基本和企業級 Web Bean 的功能。若要有效使用 specialization,擁有較高優先權的 Web Bean 必須:
是個它所置換的 Web Bean 的直接 subclass,並且
若它所置換的 Web Bean 是個基本的 Web Bean,它就必須是個基本 Web Bean,或是若它所置換的 Web Bean 是個企業級的 Web Bean,那它就必須是個企業級的 Web Bean,並且
需被標記 @Specializes
。
@Stateless @Staging @Specializes
public class StagingCreditCardPaymentProcessor
extends CreditCardPaymentProcessor {
...
}
優先權較高的 Web Bean 會 specializes 它的 superclass。
當使用了 specialization 時:
superclass 的綁定類型就會自動地被標記為 @Specializes
的 Web Bean 繼承,並且
superclass 的 Web Bean 名稱會自動地被標記為 @Specializes
的 Web Bean 繼承,並且
superclass 所宣告的 producer method、disposal method 以及 observer method 會被一個標記了 @Specializes
的 Web Bean instance 調用。
在我們的範例中,CreditCardPaymentProcessor
的 @CreditCard
綁定類型會被 StagingCreditCardPaymentProcessor
繼承。
另外,Web Bean 管理員會針對於以下情形進行驗證:
superclass 的所有 API 類型都會是標記為 @Specializes
的 Web Bean 的 API 類型(superclass enterprise bean 的所有本地介面也都屬於 subclass 的本地介面)、
標記為 @Specializes
的 Web Bean 的 deployment type 擁有比 superclass 的 deployment type 還要高的優先權,以及
沒有其它已啟用的 Web Bean 會 specialize 該 superclass。
若任何的這些條件被違反的話,Web Bean 管理員便會在初始化時回傳一個 exception。
因此,我們能夠確定當標記為 @Specializes
的 Web Bean 被建置並啟用的情況下,superclass 絕不會在系統的任何 deployment 中被調用。