(翻譯)JavaEE6規范 CDI教程第三部分

          (譯)JavaEE6規范 CDI教程第三部分

          kuuyee  |  2011-06-11  |  JEE   CDI  

          本部分講述@Alternative@Qualfiers

          使用@Alternative來選擇一個替代者

          你可能還記得,我們在前面定義了幾個可作為替代選擇的傳輸器,分別是JsonRestAtmTransportSoapRestAtmTransport。想象一下如果你是ATM的安裝者,那么需要配置傳輸器和地點。我們之前定義的注入點只是使用默認傳輸器StandardRestAtmTransport

          如果還需要不同的傳輸器,就需要更改/META-INF/beans.xml文件來正確的選擇傳輸器,如下:

          <!-- {classpath}/META-INF/beans.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 http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
          <alternatives>
          <class>org.cdi.advocacy.JsonRestAtmTransport</class>
          </alternatives>
          </beans>

          你在輸出中將會看到選擇使用了JSON REST傳輸器。 Output

          deposit called         
          communicating with bank via JSON REST transport

          替代選擇在DI中是非常普遍的場景應用,也就是說,你有不同的注入對象依賴于不同的構建環境。很棒的是對象可以被替換。替代選擇特性允許你標記對象可以被其它對象替換。

          如果DI容器有選擇替代功能,可以讓你標記對象能夠被替代。請考慮使用這種方式。因為我們不需要非得在文檔中說明替代選擇,他自身就是一種文檔,如果某些人知道CDI并且知道替代選擇,那么他們在看到它時不會感到陌生。替代選擇是讓你替代對象的標準方式。

          你可以考慮使用CDI作為很多模式的標準,我們已經在很多純DI框架中使用過。簡單化和標準化是DI的發展方向的一部分。 2. 使用@Qualifier注入不同的類型 在CDI中所有的對象和生產者都是限定類型的。如果你沒有分配限定類型那么將會使用默認的@Default和@Any。就像一個罪犯在美國,如果沒有足夠的錢給律師,那么他將會被分配一個。 限定類型用來識別正確的對象被注入,你可以寫自己定制的限定類型。 限定類型能夠匹配注入目標和注入源,確保正確的類型被注入。 你可以決定在什么時候注入Soap、Json和Standard傳輸器。你不想把他們列出來選擇,實際上,你想在某些時候使用Json實現.

          下面是對于Soap的一個限定類型定義。

           Soap 
          package org.cdi.advocacy;

          import java.lang.annotation.Retention;
          import java.lang.annotation.Target;
          import static java.lang.annotation.ElementType.*;
          import static java.lang.annotation.RetentionPolicy.*;
          import javax.inject.Qualifier;
          @Qualifier @Retention(RUNTIME)
          @Target({TYPE, METHOD, FIELD, PARAMETER})
          public @interface Soap { }

          注意一個限定類型就是一個運行時注解,其標注了@Qualifier注解。@Qualifier注解把一個運行時注解聲明為限定類型。

          下面我在SoapAtmTransport使用一個新的限定類型@Soap:

          // SoapAtmTransport使用新的@Soap限定類型注解 
          package org.cdi.advocacy;
          @Soap public class SoapAtmTransport implements ATMTransport {
          @Override
          public void communicateWithBank(byte[] datapacket) {
          System.out.println("communicating with bank via Soap transport");
          }
          }
          Soap [source,java]

          public class AutomatedTellerMachineImpl implements AutomatedTellerMachine {

          private ATMTransport transport;
          @Inject public AutomatedTellerMachineImpl(@Soap ATMTransport transport) {
          this.transport = transport;
          }
          你也可以使用setter方法參數來標注限定類型,如下: [source,java]

          public class AutomatedTellerMachineImpl implements AutomatedTellerMachine {

          private ATMTransport transport;
          @Inject public void setTransport(@Soap ATMTransport transport) {
          this.transport = transport;
          }
          最通用的方法就是使用變量域層注入,如下: [source,java]

          public class AutomatedTellerMachineImpl implements AutomatedTellerMachine {

                  @Inject @Soap         private ATMTransport transport; ---

          到這里,我們下面將使用變量域層注入來簡化我們的例子。

          使用@Qualfiers在同一個bean中注入多個類型

          我們假設ATM機使用不同的傳輸器是基于一些不同的商業規則,比如是LDAP或者XML或者數據庫。

          你需要聲明在運行時使用哪個傳輸器。

          在這個例子中我們希望注入三個不同的傳輸器并且基于商業規則配置傳輸器。

          你需要通知在注入完成時bean已經被CDI準備好了。要獲得這個通知你需要在init方法上標注@PostConstruct注解,這樣你就能區分使用哪種類型的傳輸器了。

          //AutomatedTellerMachineImpl使用新的多個限定類型注解注入多個傳輸器 
          package org.cdi.advocacy;

          import java.math.BigDecimal;
          import javax.annotation.PostConstruct;
          import javax.inject.Inject;
          import javax.inject.Named;

          @Named("atm")
          public class AutomatedTellerMachineImpl implements AutomatedTellerMachine {
          private ATMTransport transport;
          @Inject @Soap
          private ATMTransport soapTransport;
          @Inject @Json
          private ATMTransport jsonTransport;
          @Inject @Json
          private ATMTransport standardTransport;
          //These could be looked up in a DB, JNDI or a properties file.
          private boolean useJSON = true;
          private boolean behindFireWall = true;
          @PostConstruct
          protected void init() {
          //Look up values for useJSON and behindFireWall
          if (!behindFireWall) {
          transport = standardTransport;
          } else {
          if (useJSON) {
          transport = jsonTransport;
          } else {
          transport = soapTransport;
          }
          }
          }
          public void deposit(BigDecimal bd) {
          System.out.println("deposit called");
          transport.communicateWithBank(null);
          }
          ...
          }

          嘗試執行上面的例子,將會得到下面的輸出。 Output

          deposit called communicating with bank via JSON REST transport

          待續..

          2011-06-11

          posted on 2011-06-20 11:43 kuuyee 閱讀(2625) 評論(1)  編輯  收藏 所屬分類: CDIJEE

          評論

          # re: (翻譯)JavaEE6規范 CDI教程第三部分 2011-06-20 13:22 寧波廢金屬回收

          博主加油,支持你哦!  回復  更多評論   

          導航

          <2011年6月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          統計

          隨筆分類(139)

          Linux內核

          搜索

          •  

          積分與排名

          • 積分 - 320264
          • 排名 - 178

          最新評論

          閱讀排行榜

          主站蜘蛛池模板: 石门县| 弥渡县| 克什克腾旗| 遂溪县| 辽宁省| 喀什市| 宜城市| 敦煌市| 嫩江县| 余江县| 铜川市| 长阳| 乌鲁木齐县| 浦县| 新乡市| 临安市| 睢宁县| 巴马| 黄石市| 沾化县| 葫芦岛市| 穆棱市| 宜君县| 桓台县| 沁源县| 宜兰市| 新蔡县| 黄龙县| 南京市| 咸宁市| 昭觉县| 牙克石市| 周口市| 永胜县| 同心县| 深泽县| 江源县| 梨树县| 冀州市| 塔城市| 疏勒县|