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

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

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

    xylz,imxylz

    關(guān)注后端架構(gòu)、中間件、分布式和并發(fā)編程

       :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      111 隨筆 :: 10 文章 :: 2680 評(píng)論 :: 0 Trackbacks


    1. 依賴注入

    1.1 類依賴注入

    所謂的綁定就是將一個(gè)接口綁定到具體的類中,這樣客戶端不用關(guān)心具體的實(shí)現(xiàn),而只需要獲取相應(yīng)的接口完成其服務(wù)即可。

    HelloWorld.java


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

    然后是具體的實(shí)現(xiàn),HelloWorldImpl.java


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

    寫一個(gè)測(cè)試?yán)涌纯矗?em>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 

    這個(gè)例子非常簡(jiǎn)單,通俗的將就是將一個(gè)HelloWorldImpl的實(shí)例與HelloWorld關(guān)聯(lián)起來(lái),當(dāng)想Guice獲取一個(gè)HelloWorld實(shí)例的時(shí)候,Guice就返回一個(gè)HelloWorldImpl的實(shí)例,然后我們就可以調(diào)用HelloWorld服務(wù)的方法了。

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


    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)測(cè)試結(jié)果告訴我們,HelloWorld不是單例的,每次都會(huì)返回一個(gè)新的實(shí)例。

    問(wèn)題(2)HelloWorld的實(shí)例是HelloWorldImpl么?可以強(qiáng)制轉(zhuǎn)型么?

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

     

    解答(2),結(jié)果輸出cn.imxylz.study.guice.helloworld.HelloWorldImpl,看來(lái)確實(shí)只是返回了一個(gè)正常的實(shí)例,并沒(méi)有做過(guò)多的轉(zhuǎn)換和代理。

    問(wèn)題(3),如果綁定多個(gè)實(shí)現(xiàn)到同一個(gè)接口上會(huì)出現(xiàn)什么情況?


    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目前看起來(lái)不允許多個(gè)實(shí)例綁定到同一個(gè)接口上了。

    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)

    問(wèn)題(4),可以綁定一個(gè)實(shí)現(xiàn)類到實(shí)現(xiàn)類么?

    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)

    我們來(lái)看看bind的語(yǔ)法。

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


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

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


    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());

    太好了,支持子類綁定,這樣即使我們將一個(gè)實(shí)現(xiàn)類發(fā)布出去了(盡管不推薦這么做),我們?cè)诤笃谌匀挥修k法替換實(shí)現(xiàn)類。

    使用bind有一個(gè)好處,由于JAVA 5以上的泛型在編譯器就確定了,所以可以幫我們檢測(cè)出綁定錯(cuò)誤的問(wèn)題,而這個(gè)在配置文件中是無(wú)法檢測(cè)出來(lái)的。

    這樣看起來(lái)Module像是一個(gè)Map,根據(jù)一個(gè)Key獲取其Value,非常簡(jiǎn)單的邏輯。

    問(wèn)題(5),可以綁定到我們自己構(gòu)造出來(lái)的實(shí)例么?

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


    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());

    問(wèn)題(6),我不想自己提供邏輯來(lái)構(gòu)造一個(gè)對(duì)象可以么?

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


     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());

    問(wèn)題(7),實(shí)現(xiàn)類可以不經(jīng)過(guò)綁定就獲取么?比如我想獲取HelloWorldImpl的實(shí)例而不通過(guò)Module綁定么?

    解答(7),可以,實(shí)際上Guice能夠自動(dòng)尋找實(shí)現(xiàn)類。


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

    問(wèn)題(8),可以使用注解方式完成注入么?不想手動(dòng)關(guān)聯(lián)實(shí)現(xiàn)類。

    解答(8),好,Guice提供了注解的方式完成關(guān)聯(lián)。我們需要在接口上指明此接口被哪個(gè)實(shí)現(xiàn)類關(guān)聯(lián)了。


    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());


    事實(shí)上對(duì)于一個(gè)已經(jīng)被注解的接口我們?nèi)匀豢梢允褂肕odule來(lái)關(guān)聯(lián),這樣獲取的實(shí)例將是Module關(guān)聯(lián)的實(shí)例,而不是@ImplementedBy注解關(guān)聯(lián)的實(shí)例。這樣仍然遵循一個(gè)原則,手動(dòng)優(yōu)于自動(dòng)。

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

     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 

    可以看到現(xiàn)在獲取的實(shí)例已經(jīng)是單例的,不再每次請(qǐng)求生成一個(gè)新的實(shí)例。事實(shí)上Guice提供兩種Scope,com.google.inject.Scopes.SINGLETON和com.google.inject.Scopes.NO_SCOPE,所謂沒(méi)有scope即是每次生成一個(gè)新的實(shí)例。

    對(duì)于自動(dòng)注入就非常簡(jiǎn)單了,只需要在實(shí)現(xiàn)類加一個(gè)Singleton注解即可。

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

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


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

    評(píng)論

    # re: Google Guice 入門教程01 - 依賴注入 2009-12-23 09:49 字典
    不錯(cuò)  回復(fù)  更多評(píng)論
      

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

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

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

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


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 精品亚洲成AV人在线观看| 亚洲日韩人妻第一页| 亚洲第一区香蕉_国产a| 四虎成人精品国产永久免费无码| 2021免费日韩视频网| 亚洲中文字幕在线观看| 中文在线免费视频| 亚洲va中文字幕无码久久不卡| 国产自国产自愉自愉免费24区| 国产精一品亚洲二区在线播放| 久久免费视频网站| 亚洲美免无码中文字幕在线| 免费精品无码AV片在线观看| 亚洲欧洲日产国码www| 中文毛片无遮挡高潮免费| 亚洲人成图片网站| 免费jjzz在线播放国产| 中国极品美軳免费观看| 亚洲人成电影在线天堂| 日本在线高清免费爱做网站| 在线亚洲高清揄拍自拍一品区| 91在线视频免费91| 暖暖免费中文在线日本| 日本亚洲欧洲免费天堂午夜看片女人员 | 国产偷国产偷亚洲高清日韩 | 亚洲熟妇无码一区二区三区| 99久久免费精品国产72精品九九| 亚洲最大的成人网| 亚洲AV日韩精品一区二区三区| 一道本不卡免费视频| 久久精品夜色国产亚洲av| 国产卡一卡二卡三免费入口| 国产成人久久精品亚洲小说| 亚洲精品成人片在线观看精品字幕| 免费A级毛片无码A∨免费| 久久精品国产亚洲AV天海翼| 亚洲国产成人一区二区精品区| 国产精品成人免费一区二区| 香蕉免费看一区二区三区| 亚洲a级在线观看| 日韩一卡2卡3卡4卡新区亚洲|