xylz,imxylz

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

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

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

          1.3.5 Scope(作用域)

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


              com.google.inject.Scopes.SINGLETON

              com.google.inject.Scopes.NO_SCOPE

          在使用上,可以使用Module的bind來實現(xiàn),看下面的例子。


           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特性),當當前線程中沒有構(gòu)造一個對象的時候先構(gòu)造一個出來,然后放入線程上下文中,以后每次都從線程中獲取對象。第50行是將WwwService服務(wù)以ThreadServiceScope的作用域綁定到Service服務(wù)上。第57-60行輸出當前對象的hashCode,如果此類是同一對象的話就應(yīng)該輸出相同的hashCode。為了看到效果,我們使用3個線程,每個線程輸出三次來看結(jié)果。

          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釋放了,結(jié)果下一個線程使用了上一個線程的相同空間,所以這里使用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外,對象默認在第一次調(diào)用時被創(chuàng)建,也即所謂的延時加載,Guice也允許對象在注入到Guice容器中時就被創(chuàng)建出來(顯然這是針對單例模式才有效)。

           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 }

          結(jié)果輸出如下:

           constuctor:26996967388652
          before call:
          26996967713635
                 doit:
          26997069993702

          可以看到我們的對象在調(diào)用getInstance之前就已經(jīng)被構(gòu)造出來了。

          1.3.7 Stages (運行階段)

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

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

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

          默認情況下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服務(wù)那么就使用默認的WwwService,否則就是用獲取的服務(wù)。如果將第7行注釋去掉我們就可以看到實際上調(diào)用的是HomeService服務(wù)了。


          到此為止,Guice依賴注入的基本教程就學(xué)習完了,下面的章節(jié)我們進入經(jīng)典的AOP教程學(xué)習。

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

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



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

          評論

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


          ©2009-2014 IMXYLZ
          主站蜘蛛池模板: 梓潼县| 东阿县| 顺昌县| 桑日县| 会泽县| 三亚市| 远安县| 都兰县| 新建县| 长宁县| 河北区| 丹阳市| 南充市| 水城县| 互助| 墨江| 怀柔区| 宁蒗| 拜城县| 安康市| 朝阳区| 江西省| 卓资县| 麻江县| 丘北县| 沁阳市| 福安市| 云林县| 原阳县| 慈溪市| 德江县| 阿拉尔市| 安平县| 四会市| 新平| 乌拉特前旗| 雅江县| 白朗县| 叶城县| 泽普县| 奎屯市|