读书人

Google Guice 二

发布时间: 2012-09-12 09:21:30 作者: rapoo

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?

读书人网 >编程

热点推荐