xylz,imxylz

关注后端架构、中间件、分布式和并发编程

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  111 随笔 :: 10 文章 :: 2680 评论 :: 0 Trackbacks

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 Guice 入门教程01 - 依赖注入(1)

下一篇:Google Guice 入门教程03 - 依赖注入(3)



©2009-2014 IMXYLZ |求贤若渴
posted on 2009-12-23 23:45 imxylz 阅读(20399) 评论(3)  编辑  收藏 所属分类: Google Guice

评论

# re: Google Guice 入门教程02 - 依赖注入(2) 2013-05-22 17:07 Teaey
在使用中发现两个问题,想请教下:
1. 通过Provider new出来的对象是不会自动注入Injdect的实例域的
2. Provider方式@Singleton注解失效,只有手动调用in(Scopes.SINGLETON);来绑定单例  回复  更多评论
  

# re: Google Guice 入门教程02 - 依赖注入(2) 2015-03-10 18:08 库特
我发现setter注入的时候,
@Inject
public void setHello2(Hello2 hello2, Hello3 hello3) {
this.hello2 = hello2;
this.hello3 = hello3;
}
或者
@Inject
public void setHello3(Hello3 hello3, Hello2 hello2) {
this.hello2 = hello2;
this.hello3 = hello3;
}
也是可以的,多setter注(好)入(假)  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航:
 

©2009-2014 IMXYLZ