天天看点

Guice框架-DI(依赖注入属性注入)

1.2.1 基本属性注入

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

 @implementedby(serviceimpl.class)

  public interface service {

      void execute();

 }

serviceimpl.java

 public class serviceimpl implements service {

    @override

    public void execute() {

        system.out.println("this is made by teny (www.teny32.blog.51cto.com).");

    }

}

fieldinjectdemo.java

 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 teny (www.teny32.blog.51cto.com)

 3  * @version $rev: 73 $

 4  */

 5 public class fieldinjectdemo2 {

12         fieldinjectdemo2 fd = new fieldinjectdemo2();

13         fd.getservcie().execute();

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

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();

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.teny32.blog.51cto.com)

 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 teny(www.teny32.blog.51cto.com)

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 {

 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());

21     }

22 

23 

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

1.2.3 setter注入(setter method inject)

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

 1     public class setterinjectdemo {

 2 

 4 

 6         public void setservice(service service) {

 7             this.service = service;

 8         }

13 

14         public static void main(string[] args) {

15             setterinjectdemo sid = guice.createinjector().getinstance(setterinjectdemo.class);

16             sid.getservice().execute();

17         }

18 

19     }

20 

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

 1     /** a demo for static field inject

 2      * @author teny (www.teny32.blog.51cto.com)

 3      * @version $rev: 78 $

 5     public class staticfieldinjectdemo {

 7         @inject

 8         private static service service;

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         }

21 

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

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

 1     public class instancefieldinjectdemo {

 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注入。

 6             instancefieldinjectdemo ifid = new instancefieldinjectdemo();

 7             guice.createinjector().injectmembers(ifid);

 8             ifid.service.execute();

11 

12