<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    xylz,imxylz

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

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


    1. 依賴注入

    1.1 類依賴注入

    所謂的綁定就是將一個接口綁定到具體的類中,這樣客戶端不用關心具體的實現,而只需要獲取相應的接口完成其服務即可。

    HelloWorld.java


    1     public interface HelloWorld {
    2 
    3         String sayHello();
    4     }
    5 

    然后是具體的實現,HelloWorldImpl.java


    1     public class HelloWorldImpl implements HelloWorld {
    2 
    3         @Override
    4         public String sayHello() {
    5             return "Hello, world!";
    6         }
    7     }
    8 

    寫一個測試例子看看,HelleWorldTest.java


     1     public class HelleWorldTest {
     2 
     3         @Test
     4         public void testSayHello() {
     5           Injector inj=  Guice.createInjector(new Module() {
     6                 @Override
     7                 public void configure(Binder binder) {
     8                     binder.bind(HelloWorld.class).to(HelloWorldImpl.class);
     9                 }
    10             });
    11           HelloWorld hw = inj.getInstance(HelloWorld.class);
    12           Assert.assertEquals(hw.sayHello(), "Hello, world!");
    13         }
    14     }
    15 

    這個例子非常簡單,通俗的將就是將一個HelloWorldImpl的實例與HelloWorld關聯起來,當想Guice獲取一個HelloWorld實例的時候,Guice就返回一個HelloWorldImpl的實例,然后我們就可以調用HelloWorld服務的方法了。

    問題(1)HelloWorld是單例的么?測試下。


    1 HelloWorld hw = inj.getInstance(HelloWorld.class); 
    2 Assert.assertEquals(hw.sayHello(), "Hello, world!");
    3 HelloWorld hw2 = inj.getInstance(HelloWorld.class);
    4 System.out.println(hw.hashCode()+"->"+hw2.hashCode());
    5 Assert.assertEquals(hw.hashCode(), hw2.hashCode());

    解答(1)測試結果告訴我們,HelloWorld不是單例的,每次都會返回一個新的實例。

    問題(2)HelloWorld的實例是HelloWorldImpl么?可以強制轉型么?

    HelloWorld hw = inj.getInstance(HelloWorld.class);
    System.out.println(hw.getClass().getName());

     

    解答(2),結果輸出cn.imxylz.study.guice.helloworld.HelloWorldImpl,看來確實只是返回了一個正常的實例,并沒有做過多的轉換和代理。

    問題(3),如果綁定多個實現到同一個接口上會出現什么情況?


    1 public class HelloWorldImplAgain implements HelloWorld {
    2     @Override
    3     public String sayHello() {
    4         return "Hello world again.";
    5     }
    6 }

    binder.bind(HelloWorld.class).to(HelloWorldImpl.class);
    binder.bind(HelloWorld.
    class).to(HelloWorldImplAgain.class);

    解答(3),很不幸,Guice目前看起來不允許多個實例綁定到同一個接口上了。

    com.google.inject.CreationException: Guice creation errors:

    1) A binding to cn.imxylz.study.guice.helloworld.HelloWorld was already configured at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:28).
      at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:29)

    問題(4),可以綁定一個實現類到實現類么?

    1 Injector inj=  Guice.createInjector(new Module() {
    2       @Override
    3       public void configure(Binder binder) {
    4           binder.bind(HelloWorldImpl.class).to(HelloWorldImpl.class);
    5       }
    6   });
    7 HelloWorld hw = inj.getInstance(HelloWorldImpl.class);
    8 System.out.println(hw.sayHello());

     

    非常不幸,不可以自己綁定到自己。

    1) Binding points to itself.
      at cn.imxylz.study.guice.helloworld.HelleWorldTest$1.configure(HelleWorldTest.java:28)

    我們來看看bind的語法。

    <T> AnnotatedBindingBuilder<T> bind(Class<T> type);


    ScopedBindingBuilder to(Class<? extends T> implementation);

    也就是說只能綁定一個類的子類到其本身。改造下,改用子類替代。


    1     public class HelloWorldSubImpl extends HelloWorldImpl {
    2 
    3         @Override
    4         public String sayHello() {
    5             return "@HelloWorldSubImpl";
    6         }
    7     }
    8 

    1 Injector inj=  Guice.createInjector(new Module() {
    2             @Override
    3             public void configure(Binder binder) {
    4                 binder.bind(HelloWorldImpl.class).to(HelloWorldSubImpl.class);
    5             }
    6         });
    7       HelloWorldImpl hw = inj.getInstance(HelloWorldImpl.class);
    8       System.out.println(hw.sayHello());

    太好了,支持子類綁定,這樣即使我們將一個實現類發布出去了(盡管不推薦這么做),我們在后期仍然有辦法替換實現類。

    使用bind有一個好處,由于JAVA 5以上的泛型在編譯器就確定了,所以可以幫我們檢測出綁定錯誤的問題,而這個在配置文件中是無法檢測出來的。

    這樣看起來Module像是一個Map,根據一個Key獲取其Value,非常簡單的邏輯。

    問題(5),可以綁定到我們自己構造出來的實例么?

    解答(5)當然可以!看下面的例子。


    1 Injector inj=  Guice.createInjector(new Module() {
    2             @Override
    3             public void configure(Binder binder) {
    4                 binder.bind(HelloWorld.class).toInstance(new HelloWorldImpl());
    5             }
    6         });
    7       HelloWorld hw = inj.getInstance(HelloWorld.class);
    8       System.out.println(hw.sayHello());

    問題(6),我不想自己提供邏輯來構造一個對象可以么?

    解答(6),可以Guice提供了一個方式(Provider<T>),允許自己提供構造對象的方式。


     1 Injector inj=  Guice.createInjector(new Module() {
     2       @Override
     3       public void configure(Binder binder) {
     4           binder.bind(HelloWorld.class).toProvider(new Provider<HelloWorld>() {
     5               @Override
     6               public HelloWorld get() {
     7                   return new HelloWorldImpl();
     8               }
     9           });
    10       }
    11   });
    12 HelloWorld hw = inj.getInstance(HelloWorld.class);
    13 System.out.println(hw.sayHello());

    問題(7),實現類可以不經過綁定就獲取么?比如我想獲取HelloWorldImpl的實例而不通過Module綁定么?

    解答(7),可以,實際上Guice能夠自動尋找實現類。


    Injector inj=  Guice.createInjector();
    HelloWorld hw 
    = inj.getInstance(HelloWorldImpl.class);
    System.out.println(hw.sayHello());

    問題(8),可以使用注解方式完成注入么?不想手動關聯實現類。

    解答(8),好,Guice提供了注解的方式完成關聯。我們需要在接口上指明此接口被哪個實現類關聯了。


    1     @ImplementedBy(HelloWorldImpl.class)
    2     public interface HelloWorld {
    3 
    4         String sayHello();
    5     }
    6 

    Injector inj=  Guice.createInjector();
    HelloWorld hw 
    = inj.getInstance(HelloWorld.class);
    System.out.println(hw.sayHello());


    事實上對于一個已經被注解的接口我們仍然可以使用Module來關聯,這樣獲取的實例將是Module關聯的實例,而不是@ImplementedBy注解關聯的實例。這樣仍然遵循一個原則,手動優于自動。

    問題(9)再回頭看問題(1)怎么綁定一個單例?

     1     Injector inj = Guice.createInjector(new Module() {
     2 
     3         @Override
     4         public void configure(Binder binder) {
     5             binder.bind(HelloWorld.class).to(HelloWorldImplAgain.class).in(Scopes.SINGLETON);
     6         }
     7     });
     8     HelloWorld hw = inj.getInstance(HelloWorld.class);
     9     HelloWorld hw2 = inj.getInstance(HelloWorld.class);
    10     System.out.println(hw.hashCode() + "->" + hw2.hashCode());
    11 

    可以看到現在獲取的實例已經是單例的,不再每次請求生成一個新的實例。事實上Guice提供兩種Scope,com.google.inject.Scopes.SINGLETON和com.google.inject.Scopes.NO_SCOPE,所謂沒有scope即是每次生成一個新的實例。

    對于自動注入就非常簡單了,只需要在實現類加一個Singleton注解即可。

    1     @Singleton
    2     public class HelloWorldImpl implements HelloWorld {
    3 
    4         @Override
    5         public String sayHello() {
    6             return "Hello, world!";
    7         }
    8     }
    9
    附:【前沿】本教程的依賴注入部分基于老菜鳥叮咚的教程,原文在此http://www.family168.com/tutorial/guice/html/。原文主要基于Google Guice 1.0版本的,本文基于Google Guice 2.0版本進行學習和討論。

    下一篇:Google Guice 入門教程02 - 依賴注入(2)


    ©2009-2014 IMXYLZ |求賢若渴
    posted on 2009-12-22 23:28 imxylz 閱讀(35741) 評論(5)  編輯  收藏 所屬分類: J2EEGoogle Guice

    評論

    # re: Google Guice 入門教程01 - 依賴注入 2009-12-23 09:49 字典
    不錯  回復  更多評論
      

    # re: Google Guice 入門教程01 - 依賴注入(1)[未登錄] 2010-07-01 09:57 Sam
    Very Nice!  回復  更多評論
      

    # re: Google Guice 入門教程01 - 依賴注入(1) 2011-06-15 23:32 RunCode
    不錯  回復  更多評論
      

    # re: Google Guice 入門教程01 - 依賴注入(1) 2012-07-25 19:00 怒破
    博主小哥,你認識張民松嗎  回復  更多評論
      

    # re: Google Guice 入門教程01 - 依賴注入(1)[未登錄] 2016-03-05 14:12 yong
    Guice的實現方式不太優雅,在配置的繼承重用和annotation侵入性上有問題,我最近做了一個小項目叫jBeanBox (不能發鏈接,請Google之) 。特點:1.只用單個Java文件350行源碼實現完整IOC/AOP 2.用Java類代替XML作為配置,支持IDE重構,無侵入性(沒用annotation),敬請評價。  回復  更多評論
      


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 啦啦啦手机完整免费高清观看| 亚洲免费一级视频| 亚洲国产香蕉人人爽成AV片久久| 亚洲AV无码资源在线观看| 在线观看免费毛片| 精品国产日韩亚洲一区在线| 成人爽A毛片免费看| 亚洲美女视频一区| 日韩不卡免费视频| 亚洲色偷偷色噜噜狠狠99网| 免费观看毛片视频| 日韩电影免费在线观看网址 | 国产精品亚洲αv天堂无码| 午夜亚洲乱码伦小说区69堂| 日韩精品无码免费专区午夜| 亚洲成a人片在线观看日本| 久久亚洲免费视频| 亚洲国产成人精品久久| 成人免费看黄20分钟| 四虎国产精品成人免费久久| 国产亚洲AV夜间福利香蕉149| 免费国产99久久久香蕉| 亚洲国产日韩在线一区| 日韩一区二区免费视频| WWW国产成人免费观看视频| 亚洲人成在线观看| 永久久久免费浮力影院| 中文字幕不卡免费高清视频| 日韩免费毛片视频| 中文字幕的电影免费网站| 91亚洲精品麻豆| 亚洲精品麻豆av| 男女免费观看在线爽爽爽视频 | 国产亚洲精品xxx| 亚洲成a人无码亚洲成www牛牛| 四虎永久免费影院| 污视频在线免费观看| 亚洲AV色欲色欲WWW| 亚洲av伊人久久综合密臀性色| 西西大胆无码视频免费| aa在线免费观看|