Guice framework-DI (scope of dependency injection)

This chapter continues to discuss other topics of dependency injection, including scope (scope, here is an example of a scope bound to a thread), immediate initialization (Eagerly Loading Bindings), runtime (Stage), option injection (Optional Injection), etc. Wait.

 

 

1.3.5 Scope

 

In chapter 1.1, we have a preliminary understanding of the singleton pattern of objects, and some common scopes are provided in Guice, such as the following two scopes for the singleton pattern.

 

 

    com.google.inject.Scopes.SINGLETON

 

    com.google.inject.Scopes.NO_SCOPE

 

In use, you can use Module's bind to achieve, see the following example.

 

 

 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 

Of course, the singleton pattern can also be annotated with @Singleton.

 

 

In the com.google.inject.binder.ScopedBindingBuilder.in(Scope) method, a Scope can be a Scope defined by itself in addition to the SINGLETION and NO_SCOPE above. The following example demonstrates an example of a Scope bound to a thread.

 

 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

 

Note that the two classes Service and WWWService from "Google Guice Getting Started Tutorial 03 - Dependency Injection" are used here. In this example, the ThreadServiceScope class is a scope bound to a thread (using the ThreadLocal feature). When an object is not constructed in the current thread, an object is constructed first, and then placed in the thread context. Get the object. Line 50 binds the WWWService service to the Service service with the scope of ThreadServiceScope. Lines 57-60 output the hashCode of the current object. If this class is the same object, it should output the same hashCode. To see the effect, we use 3 threads, each thread outputs three times to see the results.

 

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

 

We see that the same object (hashCode 18303751) is output three times for the same thread (say Thread-0), which is different from the hashCode of thread 2 and thread 3.

 

(Special note: if two threads output the same hashCode, don't panic, it is because the address space of the object generated by the previous thread may be released by the GC, and the next thread uses the same space of the previous thread, so here use Thread.sleep to reduce this possibility)

 

 

In fact there are scopes bound to request and session in guice-servlet-2.0.jar.

 

com.google.inject.servlet.ServletScopes.REQUEST

com.google.inject.servlet.ServletScopes.SESSION

 

1.3.6 Eagerly Loading Bindings (Initialize Immediately)

 

 

In addition to being able to bind the scope, the object is created by default when it is called for the first time, which is the so-called lazy loading. Guice also allows objects to be created when injected into the Guice container (obviously this is only for the singleton mode. efficient).

 

 1 public class EagerSingletonDemo {

 2 

 3     public EagerSingletonDemo() {

 4         System.out.println(" constuctor:"+System.nanoTime());

 5     }

 6 void must() {

 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 }

 

The resulting output is as follows:

 

 constuctor:26996967388652

before call:26996967713635

       must:26997069993702

 

You can see that our object has been constructed before calling getInstance.

 

 

1.3.7 Stages

 

Guice also has a special effect, you can specify the Guice running mode to control the loading speed of Guice. TOOL, DEVELOPMENT, and PRODUCTION are provided in the com.google.inject.Stage enumeration.

 

TOOL describes the operation mode with plug-ins such as IDE; DEVELOPMENT refers to loading only the functions it needs during the development phase (deferred loading is used for non-immediately initialized singleton objects), so as to reduce the time for loading unneeded functions; and PRODUCTION mode means to fully load all functions (immediate loading method for singleton objects), so that problems can be found earlier, so as not to find problems when certain functions are needed (know that some of our functions may require specific conditions to trigger).

 

In fact, it is only useful when there are more singleton objects and the construction of singleton objects is time-consuming. In most cases this performance is probably negligible.

 

 

Guice uses DEVELOPMENT mode by default.

 

 

 

 

 

1.3.8 Optional Injection

 

Option injection describes that if an object cannot be injected from the Guice container, then a default object can be used. See the example below.

 

 

 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 }

 

The second line in the above example describes option injection. If a Service service cannot be obtained from the Guice container, the default WWWService is used, otherwise the obtained service is used. If we remove the comment on line 7, we can see that the HomeService service is actually called.

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327012986&siteId=291194637