xylz,imxylz

          關注后端架構、中間件、分布式和并發編程

             :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            111 隨筆 :: 10 文章 :: 2680 評論 :: 0 Trackbacks

          1.3 更多話題

          1.3.1 接口多實現

          如果一個接口有多個實現,這樣通過@Inject和Module都難以直接實現,但是這種現象確實是存在的,于是Guice提供了其它注入方式來解決此問題。比如下面的自定義注解。


          1     public interface Service {
          2 
          3         void execute();
          4     }
          5 
          6 

          1 public class HomeService implements Service {
          2     @Override
          3     public void execute() {
          4         System.out.println("home.imxylz.cn");
          5     }
          6 }

          1 public class WwwService implements Service {
          2     @Override
          3     public void execute() {
          4         System.out.println("www.imxylz.cn");
          5     }
          6 }

          1 @Retention(RetentionPolicy.RUNTIME)
          2 @Target({FIELD,PARAMETER})
          3 @BindingAnnotation
          4 public @interface Home {
          5 }

          1 @Retention(RetentionPolicy.RUNTIME)
          2 @Target({FIELD,PARAMETER})
          3 @BindingAnnotation
          4 public @interface Www {
          5 }

          上面的代碼描述的是一個Service服務,有WwwService和HomeService兩個實現,同時有Www和Home兩個注解(如果對注解各個參數不明白的需要單獨去學習JAVA 5注解)。好了下面請出我們的主角。
           1     /**
           2      * $Id: MultiInterfaceServiceDemo.java 82 2009-12-24 06:55:16Z xylz $
           3      * xylz study project (www.imxylz.cn)
           4      */
           5     package cn.imxylz.study.guice.inject.more;
           6 
           7     import com.google.inject.Binder;
           8     import com.google.inject.Guice;
           9     import com.google.inject.Inject;
          10     import com.google.inject.Module;
          11 
          12     /** a demo with multi interfaces
          13      * @author xylz (www.imxylz.cn)
          14      * @version $Rev: 82 $
          15      */
          16     public class MultiInterfaceServiceDemo {
          17         @Inject
          18         @Www
          19         private Service wwwService;
          20         @Inject
          21         @Home
          22         private Service homeService;
          23         public static void main(String[] args) {
          24             MultiInterfaceServiceDemo misd = Guice.createInjector(new Module() {
          25                 @Override
          26                 public void configure(Binder binder) {
          27                     binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class);
          28                     binder.bind(Service.class).annotatedWith(Home.class).to(HomeService.class);
          29                 }
          30             }).getInstance(MultiInterfaceServiceDemo.class);
          31             misd.homeService.execute();
          32             misd.wwwService.execute();
          33         }
          34     }
          35 
          36 

          此類的結構是注入兩個Service服務,其中wwwService是注入@Www注解關聯的WwwService服務,而homeService是注入@Home注解關聯的HomeService服務。

          同樣關于此結構我們要問幾個問題。

          問題(1)靜態注入多個服務怎么寫?

          其實,參照教程02,我們可以使用下面的例子。


           1 public class StaticMultiInterfaceServiceDemo {
           2     @Inject
           3     @Www
           4     private static Service wwwService;
           5     @Inject
           6     @Home
           7     private static Service homeService;
           8     public static void main(String[] args) {
           9        Guice.createInjector(new Module() {
          10             @Override
          11             public void configure(Binder binder) {
          12                 binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class);
          13                 binder.bind(Service.class).annotatedWith(Home.class).to(HomeService.class);
          14                 binder.requestStaticInjection(StaticMultiInterfaceServiceDemo.class);
          15             }
          16         });
          17         StaticMultiInterfaceServiceDemo.homeService.execute();
          18         StaticMultiInterfaceServiceDemo.wwwService.execute();
          19     }
          20 }

          問題(2):如果不小心一個屬性綁定了多個接口怎么辦?

          非常不幸,你將得到類似一下的錯誤,也就是說不可以綁定多個服務。


          1) cn.imxylz.study.guice.inject.more.StaticMultiInterfaceServiceDemo.wwwService has more than one annotation annotated with @BindingAnnotation: cn.imxylz.study.guice.inject.more.Www and cn.imxylz.study.guice.inject.more.Home
            at cn.imxylz.study.guice.inject.more.StaticMultiInterfaceServiceDemo.wwwService(StaticMultiInterfaceServiceDemo.java:
          17)

          問題(3):我太懶了不想寫注解來區分多個服務,怎么辦?

          程序員都是懶惰的,于是Google幫我們提供了一個Names的模板來生成注解。看下面的例子。


           1 public class NoAnnotationMultiInterfaceServiceDemo {
           2     @Inject
           3     @Named("Www")
           4     private static Service wwwService;
           5     @Inject
           6     @Named("Home")
           7     private static Service homeService;
           8     public static void main(String[] args) {
           9        Guice.createInjector(new Module() {
          10             @Override
          11             public void configure(Binder binder) {
          12                 binder.bind(Service.class).annotatedWith(Names.named("Www")).to(WwwService.class);
          13                 binder.bind(Service.class).annotatedWith(Names.named("Home")).to(HomeService.class);
          14                 binder.requestStaticInjection(NoAnnotationMultiInterfaceServiceDemo.class);
          15             }
          16         });
          17         NoAnnotationMultiInterfaceServiceDemo.homeService.execute();
          18         NoAnnotationMultiInterfaceServiceDemo.wwwService.execute();
          19     }
          20 }

          上面的例子中我們使用Named來標注我們的服務應該使用什么樣的注解,當然前提是我們已經將相應的服務與注解關聯起來了。

          1.3.2 Provider注入

          在教程第一篇中我們提到了可以通過Provider注入一個服務,這里詳細說說這種模式。

          首先我們需要構造一個Provider<T>出來。


          1     public class WwwServiceProvider implements Provider<Service> {
          2 
          3         @Override
          4         public Service get() {
          5             return new WwwService();
          6         }
          7     }
          8 
          9 

          上面的Provider的意思很簡單,每次新建一個新的WwwService對象出來。

          注入的過程看下面的代碼。


           1     public class ProviderServiceDemo {
           2 
           3         @Inject
           4         private Service service;
           5 
           6         public static void main(String[] args) {
           7             Injector inj=  Guice.createInjector(new Module() {
           8                 @Override
           9                 public void configure(Binder binder) {
          10                     binder.bind(Service.class).toProvider(WwwServiceProvider.class);
          11                 }
          12             });
          13             ProviderServiceDemo psd = inj.getInstance(ProviderServiceDemo.class);
          14             psd.service.execute();
          15         }
          16 
          17     }
          18 
          19 

          很顯然如果這東西和線程綁定就非常好了,比如我們可以使用ThreadLocal來做線程的對象交換。

          當然如果想自動注入(不使用Module手動關聯)服務的話,可以使用@ProviderBy注解。


          1     @ProvidedBy(WwwServiceProvider.class)
          2     public interface Service {
          3 
          4         void execute();
          5     }
          6 
          7 

          這樣我們就不必使用Module將Provider綁定到Service上,獲取服務就很簡單了。


          ProviderServiceDemo psd = Guice.createInjector().getInstance(ProviderServiceDemo.class);
          psd.service.execute();

          除了上述兩種方式我們還可以注入Provider,而不是注入服務,比如下面的例子例子中,屬性不再是Service,而是一個Provider<Service>。


           1     public class ProviderServiceDemo {
           2 
           3         @Inject
           4         private Provider<Service> provider;
           5 
           6         public static void main(String[] args) {
           7             ProviderServiceDemo psd = Guice.createInjector(new Module() {
           8                 @Override
           9                 public void configure(Binder binder) {
          10                     binder.bind(Service.class).toProvider(WwwServiceProvider.class);
          11                 }
          12             }).getInstance(ProviderServiceDemo.class);
          13             psd.provider.get().execute();
          14         }
          15     }
          16 
          17 

          當然了,由于我們WwwServiceProvider每次都是構造一個新的服務出來,因此在類ProviderServiceDemo中的provider每次獲取的服務也是不一樣的。

          1.3.3 綁定常量

          看看下面的例子,演示了一個綁定整數值到實例的例子。


           1     public class ConstantInjectDemo {
           2 
           3         @Inject
           4         @Named("v")
           5         private int v;
           6         public static void main(String[] args) {
           7 
           8             ConstantInjectDemo cid = Guice.createInjector(new Module() {
           9                 @Override
          10                 public void configure(Binder binder) {
          11                     binder.bindConstant().annotatedWith(Names.named("v")).to(12);
          12                 }
          13             }).getInstance(ConstantInjectDemo.class);
          14             System.out.println(cid.v);
          15         }
          16     }
          17 
          18 

          當然,既然可以使用Named,也就可以使用自己寫注解了。但是看起來好像沒有多大作用。除了上述寫法,也可以用下面的方式實現。

          binder.bind(int.class).annotatedWith(Names.named("v")).toInstance(12);

          除了可以綁定int外,在ConstantBindingBuilder類中還可以綁定其它的基本類型。

          com.google.inject.binder.ConstantBindingBuilder.to(String)
          com.google.inject.binder.ConstantBindingBuilder.to(
          long)
          com.google.inject.binder.ConstantBindingBuilder.to(
          boolean)
          com.google.inject.binder.ConstantBindingBuilder.to(
          double)
          com.google.inject.binder.ConstantBindingBuilder.to(
          float)
          com.google.inject.binder.ConstantBindingBuilder.to(
          short)
          com.google.inject.binder.ConstantBindingBuilder.to(
          char)

           

          1.3.4 綁定Properties

          除了可以綁定基本類型外,還可以綁定一個Properties到Guice中,當然了,由于Properties本質上時一個Map<String,String>,因此Guice也允許綁定一個Map<String,String>。


           1     @Inject
           2     @Named("web")
           3     private String web;
           4 
           5     public static void main(String[] args) {
           6 
           7         ConstantInjectDemo cid = Guice.createInjector(new Module() {
           8             @Override
           9             public void configure(Binder binder) {
          10                 Properties properties= new Properties();
          11                 properties.setProperty("web""www.imxylz.cn");
          12                 Names.bindProperties(binder, properties);
          13             }
          14         }).getInstance(ConstantInjectDemo.class);
          15         System.out.println(cid.web);
          16     }
          17 
          18 
           
          上一篇:Google Guice 入門教程02 - 依賴注入(2)
          下一篇:Google Guice 入門教程04 - 依賴注入(4)

          ©2009-2014 IMXYLZ |求賢若渴
          posted on 2009-12-24 19:13 imxylz 閱讀(18689) 評論(1)  編輯  收藏 所屬分類: Google Guice

          評論

          # re: Google Guice 入門教程03 - 依賴注入(3) 2013-11-16 10:56 cyning
          給你提個錯誤吧 第一個MultiInterfaceServiceDemo中的service全部是private 下面的demo對象有訪問權限 這個不對吧 訪問權限應該是public吧  回復  更多評論
            


          ©2009-2014 IMXYLZ
          主站蜘蛛池模板: 伊春市| 邛崃市| 富宁县| 轮台县| 习水县| 延吉市| 安塞县| 承德市| 于都县| 咸宁市| 延川县| 南投市| 陇川县| 华宁县| 枝江市| 泸西县| 聊城市| 宝清县| 肃宁县| 鹤岗市| 丰台区| 林芝县| 福建省| 宝清县| 玉树县| 荥经县| 通山县| 福海县| 湖南省| 忻州市| 天水市| 澄江县| 布尔津县| 湘阴县| 房产| 合肥市| 子长县| 历史| 拜城县| 乌海市| 广宗县|