<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

    6 Guice的IOC容器

    6.1 注入過程

    在前面的教程中我們講了Guice注入例子,在使用上具體描述了Guice的注入過程。在下面的篇幅中我們從源碼級了解了Guice的注入過程。

    我們從具體到抽象再到具體的深入了解Guice的內部運作機制 。

    下面一張序列圖就是描述了Guice最簡單的一次注入過程。比如下面的例子是我們熟悉的。

     1 public class HelloWorldDemo {
     2     public static void main(String[] args) {
     3         Injector inj = Guice.createInjector(new Module() {
     4             @Override
     5             public void configure(Binder binder) {
     6                 binder.bind(HelloWorld.class).to(HelloWorldImpl.class);
     7             }
     8         });
     9         HelloWorld hw = inj.getInstance(HelloWorld.class);
    10         hw.sayHello();
    11         //
    12     }
    13 }

     

     

    GuiceInject01

    從上面的圖像可以看到我們的核心是Guice如何將我們的實例注入到Injector中的,這樣客戶端才能在Injector查找我們需要的服務。

    我們進入Guice的createInjector方法,看看Guice到底做了什么操作。

    public static Injector createInjector(Module modules) {
        
    return createInjector(Arrays.asList(modules));
      }
       
    public static Injector createInjector(Iterable<? extends Module> modules) {
        
    return createInjector(Stage.DEVELOPMENT, modules);
      }
      
    public static Injector createInjector(Stage stage, Module modules) {
        
    return createInjector(stage, Arrays.asList(modules));
      }
      
    public static Injector createInjector(Stage stage,
          Iterable
    <? extends Module> modules) {
        
    return new InjectorBuilder()
            .stage(stage)
            .addModules(modules)
            .build();
      }

     

    從上面的代碼可以看到我們的Injector是被InjectorBuilder以Builder的模式構造出來的。同時我們也可以注入多個Module,并且默認情況下Guice是以Stage.DEVELOPMENT模式運行的。

    在進入我們最核心的InjectorBuilder之前,我們先簡化下模型。所謂的IOC容器,或者說DI容器,我們可以看做是一個特殊的Map,這個Map能夠將我們的對象按照某種Key(鍵值)的方式存入,然后客戶端能夠根據Key來獲取我們的對象。因此為了了解Guice容器的內部結構,我們先要了解下Guice容器中存放一個對象的Key到底是什么。

    6.2 容器Key

    在Guice中用com.google.inject.Key<T>對象來描述一個實例可以對應的Key。

    我們可以想象,如果我們以某種類型來從Map中獲取結果,那么對于同一種類型每次獲取的結果就一樣。看似滿足需求。但是如果某一種類型對應多種實例怎么辦?這種情況下我們就需要我們的Key不僅支持類型,還附帶另外一點點東西。Guice是完全基于Annotation的,沒有類似spring那樣唯一id的概念,于是在Guice中描述一個Key就是靠類型和注解來完成的。在基礎教程中我們看到了對于同一種類型,加了不同的注解獲取的就是不同的實例。

    在Java中每一個對象都有一個類型的概念,即使私有類型比如int,boolean也是有類型的概念,但是自從Java 5推出泛型以后,一直沒有一種描述泛型的類型。比如說List<String>在Java中使用List類型來描述的。但是盡管JVM有運行時擦除泛型的特點,卻又有能夠獲取編譯前類型的特性,因此實際上List<String>和List<Integer>對于我們來說應該是兩種不同的類型。

    Guice自創造了一種描述類型的方式,包括泛型類型。在Guice中使用com.google.inject.TypeLiteral<T>類描述所有的類型(包括泛型類型)。我們可以寫一個小的例子來看看。

    /**
    * $Id: TypeLiteralDemo.java 110 2010-01-08 03:06:53Z xylz $
    * xylz study project (www.imxylz.cn)
    */
    package cn.imxylz.study.guice.inner;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.Map;
    import com.google.inject.TypeLiteral;
    /** a demo for using {@link TypeLiteral}
    @author xylz (www.imxylz.cn)
    @version $Rev: 110 $
    */
    public class TypeLiteralDemo {
        
    public static void main(String[] args) throws Exception{
            
    //
            System.out.println(String.format("guice type:%s", TypeLiteral.get(Boolean.class)));
            System.out.println(String.format(
    "java type:%s", Boolean.class));
            System.out.println();
            
    //
            System.out.println(String.format("guice type:%s", TypeLiteral.get(int.class)));
            System.out.println(String.format(
    "java type:%s"int.class));
            System.out.println();
            
    //
            System.out.println(String.format("guice type:%s"new TypeLiteral<Map<Integer, String>>(){}));
            System.out.println(String.format(
    "java type:%s"new HashMap<Integer,String>().getClass()));
            System.out.println();
            
    //
            Method m = Map.class.getMethod("keySet"new Class[0]);
            System.out.println(String.format(
    "java type:%s", m.getReturnType()));
            System.out.println(String.format(
    "java generic type:%s", m.getGenericReturnType()));
            System.out.println(String.format(
    "guice type:%s", TypeLiteral.get(m.getGenericReturnType())));
            System.out.println();
            TypeLiteral
    <Map<Integer, String>> mapType = new TypeLiteral<Map<Integer, String>>() {};
            System.out.println(String.format(
    "guice type:%s", mapType.getReturnType(m)));
        }
    }

     

    下面是一次輸出結果。

    guice type:java.lang.Boolean
    java type:
    class java.lang.Boolean
    guice type:
    int
    java type:
    int
    guice type:java.util.Map
    <java.lang.Integer, java.lang.String>
    java type:
    class java.util.HashMap
    java type:
    interface java.util.Set
    java generic type:java.util.Set
    <K>
    guice type:java.util.Set
    <K>
    guice type:java.util.Set
    <java.lang.Integer>

     

    從上面的結果可以看出,Java通過一些反射機制描述了部分泛型的類型(使用java.lang.reflect.ParameterizedType來描述,其它類型使用java.lang.reflect.Type來描述,注意Class是實現了Type接口的),但是并不完整,因此Guice重寫了這部分。

     

    image

    在上面的類圖中我們可以看到,一個key是包含一個類型描述(TypeLiteral)和一個AnnotationStrategy的。AnnotationStrategy是由Annotation以及Annotation的類型組成。而TypeLiteral包含私有類型Class和對Key的引用的。

    總之在Guice中是通過類型描述和注解(Key)來完整實例描述的,通過一個Key就我們能夠從Guice容器(Injector)中獲取我們需要的實例,至于這個實例是單個實例還是一組實例(Set或者Map類型的實例),后面會繼續探討。

    上一篇:Google Guice 高級教程01 - 源碼目錄

    下一篇:待續



    ©2009-2014 IMXYLZ |求賢若渴
    posted on 2010-01-08 11:46 imxylz 閱讀(28075) 評論(6)  編輯  收藏 所屬分類: Google Guice

    評論

    # re: Google Guice 高級教程02 - Guice的IOC容器(1) 2010-01-08 12:30 凡客誠品官方網站
    順風使舵模仿  回復  更多評論
      

    # re: Google Guice 高級教程02 - Guice的IOC容器(1) 2010-01-12 09:34 ruanchao
    好,多謝,希望有jersey與Guice結合的介紹。  回復  更多評論
      

    # re: Google Guice 高級教程02 - Guice的IOC容器(1) 2011-03-18 17:06 forge
    您覺得Weld和Guice哪個更具優勢  回復  更多評論
      

    # re: Google Guice 高級教程02 - Guice的IOC容器(1) 2011-03-18 17:22 xylz
    @forge
    Weld不熟悉,為了此問題特地去看了官方站點http://seamframework.org/Weld。我感覺從官方態度以及規范、支持力度來看的話Weld可能比較有權威性,畢竟指定此規范JSR299(http://jcp.org/en/jsr/detail?id=299)的人就是RedHat自家的人。另外上面的貢獻者也比較多,說明項目可能比較活躍。
    Guice來說由于是輕量級的,所以可能比較容易使用和受關注,而且開發者也是比較有激情的小伙子,但是官方站點http://code.google.com/p/google-guice/的更新有點慢,活躍度明顯放緩,并且文檔、知識庫、論壇也不全。
    結論是,從使用以及規范角度上講選用Weld(畢竟在Seam中大力推廣,而且Jboss也有一套完整的解決方案)是比較合適的,從流行技術上倒是可以關注Guice。當然也不排除Guice發展壯大了以至于影響整個J2EE,就像當初SPRING對EJB的挑戰一樣。  回復  更多評論
      

    # re: Google Guice 高級教程02 - Guice的IOC容器(1)[未登錄] 2011-03-30 12:36 kevin
    快點更新哦,博主太NB了,偶然看到這個網站,寫得很好,收藏這個網址了。  回復  更多評論
      

    # re: Google Guice 高級教程02 - Guice的IOC容器(1) 2013-07-03 11:00 路過
    求持續更新。。。  回復  更多評論
      


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 日本高清在线免费| 亚欧免费无码aⅴ在线观看| 一级毛片一级毛片免费毛片| 91av免费在线视频| 97在线视频免费播放| 最近中文字幕无免费视频| 亚洲av无码国产精品色在线看不卡| 精品亚洲一区二区三区在线播放| 亚洲av网址在线观看| 亚洲乱码一二三四五六区| 色窝窝亚洲av网| 丁香花在线视频观看免费| 四虎永久在线观看免费网站网址| 最近2019中文字幕mv免费看| 亚洲国产成人乱码精品女人久久久不卡 | 亚洲人成无码网站在线观看| 深夜福利在线免费观看| 日本高清免费观看| 四色在线精品免费观看| 亚洲午夜久久久久久久久久| 亚洲人成777在线播放| 一二三区免费视频| 午夜国产精品免费观看| 亚洲一区二区三区乱码A| 亚洲精品成人图区| 一级特级aaaa毛片免费观看| 18禁美女裸体免费网站| 亚洲高清成人一区二区三区| 亚洲黄色免费观看| 免费人人潮人人爽一区二区| 57pao国产成视频免费播放| 成人亚洲综合天堂| 亚洲精品国产肉丝袜久久| 一区二区免费在线观看| 99久久99久久精品免费看蜜桃| 亚洲人成无码久久电影网站| 亚洲人成图片网站| 日韩精品免费视频| 亚洲福利视频一区二区| 亚洲午夜在线播放| 免费人妻无码不卡中文字幕系|