CDI(Weld)高級<6> Specialization and alternatives

當多個版本的bean來實現不一樣的目的,在開發過程當中,須要在多個Bean版本之間切換.而沒必要更改源代碼的應用程序,能夠選擇在部署時使用 @Alternative
CDI @Alternative方案一般用於如下目的,如:
1.     爲了處理客戶特定的業務邏輯在運行時肯定。
2.     要指定Bean的有效期爲一個特定的部署方案,例如,特定國家的銷售稅的法律時,須要針對具體國家的銷售稅業務邏輯。
3.     用於測試的模擬版本。
這個狀況下本章的 @Alternative 和 @Specializes內容就是你要學習的.

1. Using alternative stereotypes

CDI容許在部署時使用替代的實現去覆蓋一個bean類型。
例如,下面bean提供了PaymentProcessor接口的默認實現:.
public class DefaultPaymentProcessor implements PaymentProcessor {
   ...
}

但在咱們的環境中,咱們不想使用這個默認的實現,因此咱們重寫了PaymentProcessor: java

@Alternative
public class StagingPaymentProcessor implements PaymentProcessor {
   ...
}

或者 app

@Alternative
public class StagingPaymentProcessor extends DefaultPaymentProcessor {
   ...
}

在bean.xml中進行配置 學習

<beans xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee">
    <alternatives>
        <class>org.credo.StagingPaymentProcessor</class>
    </alternatives>
</beans>

這樣就在項目啓動的時候使用了指定的實現. 測試

但不可能一個個的在bean.xml中配置.CDI提供了更方便的方法.以下
先定義一個Stereotype,注意,其包含了@Alternative註解.
@Alternative
@Stereotype
@Retention(RUNTIME)
@Target(TYPE)
public @interface Staging {}

在咱們這個環境要使用的Bean實現上加@Staging Stereotype註解. spa

@Staging
public class StagingPaymentProcessor implements PaymentProcessor {
   ...
}

最後咱們在bean.xml中僅需如此配置 .net

<beans
   xmlns="http://xmlns.jcp.org/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://xmlns.jcp.org/xml/ns/javaee
      http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">
   <alternatives>
         <stereotype>org.mycompany.myapp.Staging</stereotype>
   </alternatives>
</beans>

如今無論有多少Staging環境下使用的替換Bean,他們都將所有啓動. code

2.alternatives的一個非嚴重缺陷

當咱們啓用替代方案,這是否意味着默認的實現被禁用?不徹底是!
若是默認的實現有一個限定詞,例如@LargeTransaction ,alternatives Bean沒有,系統仍然會注入的默認實現.例如
@Inject @LargeTransaction PaymentProcessor paymentProcessor;

因此咱們在系統中尚未徹底取代該默認實現,一個alternatives Bean在全部注射點能夠徹底重寫默認bean的惟一方法是alternatives Bean實現全部bean類型,全部限定符。好比上面PaymentProcessor 的alternatives Bean也加入了@LargeTransaction註解. xml

可是,若是默認的Bean申明瞭一個producer方法或者一個觀察者方法(cdi event 事件),那麼即時是如上述所說的那樣作,也仍是不夠的.咱們須要進行額外的一些處理.

CDI提供了一個特殊的功能,叫作specialization(專業化),能夠幫助開發者避免這些陷阱。specialization是通知系統的方式來徹底替代和禁用一個bean的實現。 繼承

3.Using specialization

針對第二節的問題,使用@Specializes來處理,以下所示: 接口

@Alternative @Specializes
public class MockCreditCardPaymentProcessor
      extends CreditCardPaymentProcessor {
   ...
}

當啓用了這個Alternative Bean,即時其餘的Bean,包括默認的Bean,申明瞭Producer方法和觀察者方法,依然使用這個Alternative Bean.


這個時候,咱們通知容器,咱們必須使用這個Alternative Bean,這個Alternative Bean也會自動繼承默認實現的全部qualifiers.
好比默認Bean有 @Default @CreditCard,那麼例子的MockCreditCardPaymentProcessor也會繼承這2個限定符. 好比默認Bean是有@Named,那麼MockCreditCardPaymentProcessor會使用默認的EL Name.至關於繼承了@Named!
相關文章
相關標籤/搜索