Google Guice 2

1.2 属性注入(Field Inject)

1.2.1 基本属性注入

首先来看一个例子。Service.java


1  @ImplementedBy(ServiceImpl. class )
2  public   interface  Service {
3       void  execute();
4  }

ServiceImpl.java


1  public   class  ServiceImpl  implements  Service {
2      @Override
3       public   void  execute() {
4          System.out.println( " This is made by imxylz (www.imxylz.cn). " );
5      }
6  }

FieldInjectDemo.java


 1  /**  a demo with Field inject
 2   *  @author  xylz (www.imxylz.cn)
 3   *  @version  $Rev: 71 $
 4    */
 5  public   class  FieldInjectDemo {
 6      @Inject
 7       private  Service servcie;
 8       public  Service getServcie() {
 9           return  servcie;
10      }
11       public   static   void  main(String[] args) {
12          FieldInjectDemo demo  =  Guice.createInjector().getInstance(FieldInjectDemo. class );
13          demo.getServcie().execute();
14      }
15  }

这个例子比较简单。具体来说就是将接口Service通过@Inject注解注入到FieldInjectDemo类中,然后再FieldInjectDemo类中使用此服务而已。当然Service服务已经通过@ImplementedBy注解关联到ServiceImpl 类中,每次生成一个新的实例(非单例)。注意,这里FieldInjectDemo类没有通过Module等关联到Guice中,具体可以查看《》。

意料之中得到了我们期待的结果。

同样,我们通过问答的方式来加深理解(注意,入门教程我们只是强调怎么使用,至于原理和底层的思想我们放到高级教程中再谈)。

问题(1):可以自己构造FieldInjectDemo 对象而不通过Guice么?


 1  /**  field inject demo2
 2   *  @author  xylz (www.imxylz.cn)
 3   *  @version  $Rev: 73 $
 4    */
 5  public   class  FieldInjectDemo2 {
 6      @Inject
 7       private  Service servcie;
 8       public  Service getServcie() {
 9           return  servcie;
10      }
11       public   static   void  main(String[] args) {
12          FieldInjectDemo2 fd  =   new  FieldInjectDemo2();
13          fd.getServcie().execute();
14      }
15  }

就像上面的例子中一样,然后运行下看看?非常不幸,我们得到了一个谁都不喜欢的结果。


Exception in thread  " main "  java.lang.NullPointerException
    at cn.imxylz.study.guice.inject.FieldInjectDemo2.main(FieldInjectDemo2.java:
22 )

很显然,由于FieldInjectDemo2不属于Guice容器(暂且称为容器吧)托管,这样Service服务没有机会被注入到FieldInjectDemo2类中。

问题(2):可以注入静态属性么?

看下面的代码。


 1  public   class  FieldInjectDemo2 {
 2      @Inject
 3       private   static  Service servcie;
 4       public   static  Service getServcie() {
 5           return  servcie;
 6      }
 7       public   static   void  main(String[] args) {
 8          FieldInjectDemo2 fd  =  Guice.createInjector().getInstance(FieldInjectDemo2. class );
 9          FieldInjectDemo2.getServcie().execute();
10      }
11  }

很不幸!运行结果告诉我们Guice看起来还不支持静态字段注入。

好了,上面两个问题我们暂且放下,我们继续学习其它注入功能。

1.2.2 构造函数注入(Constructor Inject)

继续看例子。例子是说明问题的很好方式。


 1       /**
 2       * $Id: ConstructorInjectDemo.java 75 2009-12-23 14:22:35Z xylz $
 3       * xylz study project (www.imxylz.cn)
 4        */
 5       package  cn.imxylz.study.guice.inject;
 6 
 7       import  com.google.inject.Guice;
 8       import  com.google.inject.Inject;
 9 
10       /**  a demo with constructor inject
11       *  @author  xylz (www.imxylz.cn)
12       *  @version  $Rev: 75 $
13        */
14       public   class  ConstructorInjectDemo {
15 
16           private  Service service;
17          @Inject
18           public  ConstructorInjectDemo(Service service) {
19               this .service = service;
20          }
21           public  Service getService() {
22               return  service;
23          }
24           public   static   void  main(String[] args) {
25              ConstructorInjectDemo cid  =  Guice.createInjector().getInstance(ConstructorInjectDemo. class );
26              cid.getService().execute();
27          }
28 
29      }
30 
31 

我们在构造函数上添加@Inject来达到自动注入的目的。构造函数注入的好处是可以保证只有一个地方来完成属性注入,这样可以确保在构造函数中完成一些初始化工作(尽管不推荐这么做)。当然构造函数注入的缺点是类的实例化与参数绑定了,限制了实例化类的方式。

问题(3):构造函数中可以自动注入多个参数么?


 1       public   class  ConstructorInjectDemo {
 2 
 3           private  Service service;
 4           private  HelloWorld helloWorld;
 5          @Inject
 6           public  ConstructorInjectDemo(Service service,HelloWorld helloWorld) {
 7               this .service = service;
 8               this .helloWorld = helloWorld;
 9          }
10           public  Service getService() {
11               return  service;
12          }
13           public  HelloWorld getHelloWorld() {
14               return  helloWorld;
15          }
16           public   static   void  main(String[] args) {
17              ConstructorInjectDemo cid  =  Guice.createInjector().getInstance(ConstructorInjectDemo. class );
18              cid.getService().execute();
19              System.out.println(cid.getHelloWorld().sayHello());
20          }
21      }
22 
23 

非常完美的支持了多参数构造函数注入。当然了没有必要写多个@Inject,而且写了的话不能通过编译。

1.2.3 Setter注入(Setter Method Inject)

有了上面的基础我们再来看Setter注入就非常简单了,只不过在setter方法上增加一个@Inject注解而已。


 1       public   class  SetterInjectDemo {
 2 
 3           private  Service service;
 4 
 5          @Inject
 6           public   void  setService(Service service) {
 7               this .service  =  service;
 8          }
 9 
10           public  Service getService() {
11               return  service;
12          }
13 
14           public   static   void  main(String[] args) {
15              SetterInjectDemo sid  =  Guice.createInjector().getInstance(SetterInjectDemo. class );
16              sid.getService().execute();
17          }
18 
19      }
20 
21 

好了我们再回头看问题2的静态注入(static inject)。下面的例子演示了如何注入一个静态的字段。


 1       /**  a demo for static field inject
 2       *  @author  xylz (www.imxylz.cn)
 3       *  @version  $Rev: 78 $
 4        */
 5       public   class  StaticFieldInjectDemo {
 6 
 7          @Inject
 8           private   static  Service service;
 9 
10           public   static   void  main(String[] args) {
11              Guice.createInjector( new  Module() {
12                  @Override
13                   public   void  configure(Binder binder) {
14                      binder.requestStaticInjection(StaticFieldInjectDemo. class );
15                  }
16              });
17              StaticFieldInjectDemo.service.execute();
18          }
19      }
20 
21 

非常棒!上面我们并没有使用Guice获取一个StaticFieldInjectDemo实例(废话),实际上static字段(属性)是类相关的,因此我们需要请求静态注入服务。但是一个好处是在外面看起来我们的服务没有Guice绑定,甚至client不知道(或者不关心)服务的注入过程。

再回到问题(1),参考上面静态注入的过程,我们可以使用下面的方式来注入实例变量的属性。


 1       public   class  InstanceFieldInjectDemo {
 2 
 3          @Inject
 4           private  Service service;
 5           public   static   void  main(String[] args) {
 6              final  InstanceFieldInjectDemo ifid  =   new  InstanceFieldInjectDemo();
 7              Guice.createInjector( new  Module() {
 8                  @Override
 9                   public   void  configure(Binder binder) {
10                      binder.requestInjection(ifid);
11                  }
12              });
13              ifid.service.execute();
14          }
15      }
16 
17 

实际上这里有一种简便的方法来注入字段,实际上此方法也支持Setter注入。


 1       public   class  InstanceFieldInjectDemo {
 2 
 3          @Inject
 4           private  Service service;
 5           public   static   void  main(String[] args) {
 6              InstanceFieldInjectDemo ifid  =   new  InstanceFieldInjectDemo();
 7              Guice.createInjector().injectMembers(ifid);
 8              ifid.service.execute();
 9          }
10      }
11 
12 

你可能感兴趣的:(Google)