<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

    本章節繼續討論依賴注入的其他話題,包括作用域(scope,這里有一個與線程綁定的作用域例子)、立即初始化(Eagerly Loading Bindings)、運行階段(Stage)、選項注入(Optional Injection)等等。

    1.3.5 Scope(作用域)

    在1.1章節中我們初步了解了對象的單例模式,在Guice中提供了一些常見的作用域,比如對于單例模式有下面兩個作用域。


        com.google.inject.Scopes.SINGLETON

        com.google.inject.Scopes.NO_SCOPE

    在使用上,可以使用Module的bind來實現,看下面的例子。


     1     public class ScopeDemo {
     2         public static void main(String[] args) {
     3 
     4             Service service = Guice.createInjector(new Module() {
     5                 @Override
     6                 public void configure(Binder binder) {
     7                     binder.bind(Service.class).to(WwwService.class).in(Scopes.SINGLETON);
     8                 }
     9             }).getInstance(Service.class);
    10             service.execute();
    11         }
    12     }
    13 
    14 

    當然單例模式還可以似乎用@Singleton注解。

    在com.google.inject.binder.ScopedBindingBuilder.in(Scope)方法中,一個Scope除了可以使上面的SINGLETION和NO_SCOPE外,還可以是自己定義的Scope。下面的例子演示了一個與線程綁定的Scope例子。

     1 /**
     2  * $Id: ThreadScopeDemo.java 90 2009-12-25 08:12:21Z 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.Injector;
    10 import com.google.inject.Key;
    11 import com.google.inject.Module;
    12 import com.google.inject.Provider;
    13 import com.google.inject.Scope;
    14 
    15 /** a demo with thread-scope
    16  * @author xylz (www.imxylz.cn)
    17  * @version $Rev: 90 $
    18  */
    19 public class ThreadScopeDemo {
    20 
    21     static class ThreadServiceScope implements Scope {
    22 
    23         static ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();
    24 
    25         @Override
    26         public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
    27             return new Provider<T>() {
    28                 @Override
    29                 public T get() {
    30                     T instance = (T) threadLocal.get();
    31                     if (instance == null) {
    32                         instance = unscoped.get();
    33                         threadLocal.set(instance);
    34                     }
    35                     return instance;
    36                 }
    37             };
    38         }
    39 
    40         @Override
    41         public String toString() {
    42             return "Scopes.ThreadServiceScope";
    43         }
    44     }
    45     
    46     public static void main(String[] args) {
    47         final Injector inj=Guice.createInjector(new Module() {
    48             @Override
    49             public void configure(Binder binder) {
    50                 binder.bind(Service.class).to(WwwService.class).in(new ThreadServiceScope());
    51             }
    52         });
    53         for(int i=0;i<3;i++) {
    54             new Thread("Thread-"+i) {
    55                 public void run() {
    56                     for(int m=0;m<3;m++) {
    57                         System.out.println(String.format("%s-%d:%d",//
    58                                 getName()//
    59                                 ,m//
    60                                 ,inj.getInstance(Service.class).hashCode()));
    61                         try {
    62                             Thread.sleep(50L);
    63                         } catch (Exception e) {
    64                         }
    65                     }
    66                 }
    67             }.start();
    68         }
    69     }
    70 }
    71 

    注意,這里用到了《Google Guice 入門教程03 - 依賴注入》的中的兩個類Service和WwwService。在本例中ThreadServiceScope類是一個與線程綁定的作用域(利用ThreadLocal特性),當當前線程中沒有構造一個對象的時候先構造一個出來,然后放入線程上下文中,以后每次都從線程中獲取對象。第50行是將WwwService服務以ThreadServiceScope的作用域綁定到Service服務上。第57-60行輸出當前對象的hashCode,如果此類是同一對象的話就應該輸出相同的hashCode。為了看到效果,我們使用3個線程,每個線程輸出三次來看結果。

    Thread-0-0:18303751
    Thread-1-0:23473608
    Thread-2-0:21480956
    Thread-1-1:23473608
    Thread-0-1:18303751
    Thread-2-1:21480956
    Thread-1-2:23473608
    Thread-2-2:21480956
    Thread-0-2:18303751

    我們看到對于同一個線程(比如說Thread-0)的三次都輸出了相同的對象(hashCode為18303751),而與線程2和線程3的hashCode不同。

    (特別說明:如果兩個線程輸出了同一個hashCode不必驚慌,那是因為可能前一個線程生成的對象的地址空間被GC釋放了,結果下一個線程使用了上一個線程的相同空間,所以這里使用Thread.sleep來降低這種可能性)

    事實上在guice-servlet-2.0.jar中有與request和session綁定的scope。

    com.google.inject.servlet.ServletScopes.REQUEST
    com.google.inject.servlet.ServletScopes.SESSION

    1.3.6 Eagerly Loading Bindings (立即初始化)

    除了可以綁定scope外,對象默認在第一次調用時被創建,也即所謂的延時加載,Guice也允許對象在注入到Guice容器中時就被創建出來(顯然這是針對單例模式才有效)。

     1 public class EagerSingletonDemo {
     2 
     3     public EagerSingletonDemo() {
     4         System.out.println(" constuctor:"+System.nanoTime());
     5     }
     6     void doit() {
     7         System.out.println("       doit:"+System.nanoTime());
     8     }
     9     public static void main(String[] args) throws Exception{
    10         Injector inj = Guice.createInjector(new Module() {
    11             @Override
    12             public void configure(Binder binder) {
    13                 binder.bind(EagerSingletonDemo.class).asEagerSingleton();
    14             }
    15         });
    16         System.out.println("before call:"+System.nanoTime());
    17         Thread.sleep(100L);
    18         inj.getInstance(EagerSingletonDemo.class).doit();
    19     }
    20 }

    結果輸出如下:

     constuctor:26996967388652
    before call:
    26996967713635
           doit:
    26997069993702

    可以看到我們的對象在調用getInstance之前就已經被構造出來了。

    1.3.7 Stages (運行階段)

    Guice還有一個特效,可以指定Guice運行模式來控制Guice的加載速度。在com.google.inject.Stage枚舉中提供了TOOL,DEVELOPMENT,PRODUCTION三種模式。

    TOOL描述的是帶有IDE等插件的運行模式;DEVELOPMENT是指在開發階段只加載自己需要的功能(對于非立即初始化單例對象采用延后加載),這樣來降低加載不需要功能的時間;而PRODUCTION模式是指完全加載所有功能(對于單例對象采用立即加載方式),這樣可以更早的發現問題,免得等需要某些功能的時候才發現問題(要知道我們某些功能可能需要特定的條件才能觸發)。

    其實只有比較多的單例對象,并且單例對象構造比較耗時的情況下才能有用。大部分情況下這點性能可能都忽略不計了。

    默認情況下Guice采用DEVELOPMENT模式。


    1.3.8 Optional Injection (選項注入 )

    選項注入描述的是如果不能從Guice容器中注入一個對象,那么可以使用一個默認的對象。看下面的例子。

     1 public class OptionalInjectionDemo {
     2     @Inject(optional=true)
     3     Service service = new WwwService();
     4     public static void main(String[] args) {
     5         Guice.createInjector(new Module() {
     6             public void configure(Binder binder) {
     7                 //binder.bind(Service.class).to(HomeService.class);
     8             }
     9         }).getInstance(OptionalInjectionDemo.class).service.execute();
    10     }
    11 }

    上述例子中第2行描述的是選項注入,如果不能從Guice容器中獲取一個Service服務那么就使用默認的WwwService,否則就是用獲取的服務。如果將第7行注釋去掉我們就可以看到實際上調用的是HomeService服務了。


    到此為止,Guice依賴注入的基本教程就學習完了,下面的章節我們進入經典的AOP教程學習。

    上一篇:Google Guice 入門教程03 - 依賴注入(3)

    下一篇:Google Guice 入門教程05 - AOP(面向切面編程)



    ©2009-2014 IMXYLZ |求賢若渴
    posted on 2009-12-25 18:02 imxylz 閱讀(16620) 評論(1)  編輯  收藏 所屬分類: J2EEGoogle Guice

    評論

    # re: Google Guice 入門教程04 - 依賴注入(4)[未登錄] 2011-03-30 12:28 kevin
    寫得 很好 學習了  回復  更多評論
      


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 免费无码又爽又刺激聊天APP| 亚洲日韩国产一区二区三区| 亚洲欧美国产国产综合一区| 日本免费一区尤物| 日本三级在线观看免费| 亚洲区精品久久一区二区三区| 国产性生交xxxxx免费| 很黄很污的网站免费| 亚洲精品久久无码av片俺去也| 亚洲VA中文字幕不卡无码| 永久免费AV无码国产网站| a毛片成人免费全部播放| 亚洲人成片在线观看| 国产成人麻豆亚洲综合无码精品 | 人人爽人人爽人人片A免费| 亚洲精品高清视频| 亚洲高清免费视频| 亚洲第一成年免费网站| 久草免费福利视频| 免费无码午夜福利片| 亚洲深深色噜噜狠狠网站| 亚洲成A∨人片在线观看不卡| 日韩精品免费一区二区三区| 鲁大师在线影院免费观看| 特级一级毛片免费看| 亚洲中文字幕乱码一区| 亚洲爆乳精品无码一区二区三区 | ass亚洲**毛茸茸pics| 国产亚洲精品a在线观看app| 国产免费av一区二区三区| 91免费人成网站在线观看18| 国产一级在线免费观看| 日韩色视频一区二区三区亚洲| 亚洲ts人妖网站| 亚洲综合在线视频| 久久亚洲国产中v天仙www| 亚洲国产精品无码久久九九| 日韩免费毛片视频| 两个人的视频高清在线观看免费| 最近最新高清免费中文字幕| a级毛片在线免费|