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