1.3 更多话题
1.3.1 接口多实现
如果一个接口有多个实现,这样通过@inject和module都难以直接实现,但是这种现象确实是存在的,于是guice提供了其它注入方式来解决此问题。比如下面的自定义注解。
1 public interface service {
2
3 void execute();
4 }
5
6
1 public class homeservice implements service {
2 @override
3 public void execute() {
4 system.out.println("home.imxylz.cn");
5 }
6 }
1 public class wwwservice implements service {
2 @override
3 public void execute() {
4 system.out.println("www.imxylz.cn");
5 }
6 }
1 @retention(retentionpolicy.runtime)
2 @target({field,parameter})
3 @bindingannotation
4 public @interface home {
5 }
1 @retention(retentionpolicy.runtime)
2 @target({field,parameter})
3 @bindingannotation
4 public @interface www {
5 }
上面的代码描述的是一个service服务,有wwwservice和homeservice两个实现,同时有www和home两个注解(如果对注解各个参数不明白的需要单独去学习java
5注解)。好了下面请出我们的主角。
1 /**
2 * $id: multiinterfaceservicedemo.java 82 2009-12-24 06:55:16z xylz $
3 * xylz study project (www.imxylz.cn)
4 */
5 package cn.imxylz.study.guice.inject.more;
6
7 import com.google.inject.binder;
8 import com.google.inject.guice;
9 import com.google.inject.inject;
10 import com.google.inject.module;
11
12 /** a demo with multi interfaces
13 * @author xylz (www.imxylz.cn)
14 * @version $rev: 82 $
15 */
16 public class multiinterfaceservicedemo {
17 @inject
18 @www
19 private service wwwservice;
20 @inject
21 @home
22 private service homeservice;
23 public static void main(string[] args) {
24 multiinterfaceservicedemo misd = guice.createinjector(new module() {
25 @override
26 public void configure(binder binder) {
27 binder.bind(service.class).annotatedwith(www.class).to(wwwservice.class);
28 binder.bind(service.class).annotatedwith(home.class).to(homeservice.class);
29 }
30 }).getinstance(multiinterfaceservicedemo.class);
31 misd.homeservice.execute();
32 misd.wwwservice.execute();
33 }
34 }
35
36
此类的结构是注入两个service服务,其中wwwservice是注入@www注解关联的wwwservice服务,而homeservice是注入@home注解关联的homeservice服务。
同样关于此结构我们要问几个问题。
问题(1)静态注入多个服务怎么写?
其实,参照教程02,我们可以使用下面的例子。
1 public class staticmultiinterfaceservicedemo {
2 @inject
3 @www
4 private static service wwwservice;
5 @inject
6 @home
7 private static service homeservice;
8 public static void main(string[] args) {
9 guice.createinjector(new module() {
10 @override
11 public void configure(binder binder) {
12 binder.bind(service.class).annotatedwith(www.class).to(wwwservice.class);
13 binder.bind(service.class).annotatedwith(home.class).to(homeservice.class);
14 binder.requeststaticinjection(staticmultiinterfaceservicedemo.class);
15 }
16 });
17 staticmultiinterfaceservicedemo.homeservice.execute();
18 staticmultiinterfaceservicedemo.wwwservice.execute();
19 }
20 }
问题(2):如果不小心一个属性绑定了多个接口怎么办?
非常不幸,你将得到类似一下的错误,也就是说不可以绑定多个服务。
1) cn.imxylz.study.guice.inject.more.staticmultiinterfaceservicedemo.wwwservice has more than one annotation annotated with @bindingannotation: cn.imxylz.study.guice.inject.more.www and cn.imxylz.study.guice.inject.more.home
at cn.imxylz.study.guice.inject.more.staticmultiinterfaceservicedemo.wwwservice(staticmultiinterfaceservicedemo.java:17)
问题(3):我太懒了不想写注解来区分多个服务,怎么办?
程序员都是懒惰的,于是google帮我们提供了一个names的模板来生成注解。看下面的例子。
1 public class noannotationmultiinterfaceservicedemo {
2 @inject
3 @named("www")
4 private static service wwwservice;
5 @inject
6 @named("home")
7 private static service homeservice;
8 public static void main(string[] args) {
9 guice.createinjector(new module() {
10 @override
11 public void configure(binder binder) {
12 binder.bind(service.class).annotatedwith(names.named("www")).to(wwwservice.class);
13 binder.bind(service.class).annotatedwith(names.named("home")).to(homeservice.class);
14 binder.requeststaticinjection(noannotationmultiinterfaceservicedemo.class);
15 }
16 });
17 noannotationmultiinterfaceservicedemo.homeservice.execute();
18 noannotationmultiinterfaceservicedemo.wwwservice.execute();
19 }
20 }
上面的例子中我们使用named来标注凯发k8网页登录的服务应该使用什么样的注解,当然前提是我们已经将相应的服务与注解关联起来了。
1.3.2 provider注入
在教程第一篇中我们提到了可以通过provider注入一个服务,这里详细说说这种模式。
首先我们需要构造一个provider出来。
1 public class wwwserviceprovider implements provider<service> {
2
3 @override
4 public service get() {
5 return new wwwservice();
6 }
7 }
8
9
上面的provider的意思很简单,每次新建一个新的wwwservice对象出来。
注入的过程看下面的代码。
1 public class providerservicedemo {
2
3 @inject
4 private service service;
5
6 public static void main(string[] args) {
7 injector inj= guice.createinjector(new module() {
8 @override
9 public void configure(binder binder) {
10 binder.bind(service.class).toprovider(wwwserviceprovider.class);
11 }
12 });
13 providerservicedemo psd = inj.getinstance(providerservicedemo.class);
14 psd.service.execute();
15 }
16
17 }
18
19
很显然如果这东西和线程绑定就非常好了,比如我们可以使用threadlocal来做线程的对象交换。
当然如果想自动注入(不使用module手动关联)服务的话,可以使用@providerby注解。
1 @providedby(wwwserviceprovider.class)
2 public interface service {
3
4 void execute();
5 }
6
7
这样我们就不必使用module将provider绑定到service上,获取服务就很简单了。
providerservicedemo psd = guice.createinjector().getinstance(providerservicedemo.class);
psd.service.execute();
除了上述两种方式我们还可以注入provider,而不是注入服务,比如下面的例子例子中,属性不再是service,而是一个provider。
1 public class providerservicedemo {
2
3 @inject
4 private provider<service> provider;
5
6 public static void main(string[] args) {
7 providerservicedemo psd = guice.createinjector(new module() {
8 @override
9 public void configure(binder binder) {
10 binder.bind(service.class).toprovider(wwwserviceprovider.class);
11 }
12 }).getinstance(providerservicedemo.class);
13 psd.provider.get().execute();
14 }
15 }
16
17
当然了,由于我们wwwserviceprovider每次都是构造一个新的服务出来,因此在类providerservicedemo中的provider每次获取的服务也是不一样的。
1.3.3 绑定常量
看看下面的例子,演示了一个绑定整数值到实例的例子。
1 public class constantinjectdemo {
2
3 @inject
4 @named("v")
5 private int v;
6 public static void main(string[] args) {
7
8 constantinjectdemo cid = guice.createinjector(new module() {
9 @override
10 public void configure(binder binder) {
11 binder.bindconstant().annotatedwith(names.named("v")).to(12);
12 }
13 }).getinstance(constantinjectdemo.class);
14 system.out.println(cid.v);
15 }
16 }
17
18
当然,既然可以使用named,也就可以使用自己写注解了。但是看起来好像没有多大作用。除了上述写法,也可以用下面的方式实现。
binder.bind(int.class).annotatedwith(names.named("v")).toinstance(12);
除了可以绑定int外,在constantbindingbuilder类中还可以绑定其它的基本类型。
com.google.inject.binder.constantbindingbuilder.to(string)
com.google.inject.binder.constantbindingbuilder.to(long)
com.google.inject.binder.constantbindingbuilder.to(boolean)
com.google.inject.binder.constantbindingbuilder.to(double)
com.google.inject.binder.constantbindingbuilder.to(float)
com.google.inject.binder.constantbindingbuilder.to(short)
com.google.inject.binder.constantbindingbuilder.to(char)
1.3.4 绑定properties
除了可以绑定基本类型外,还可以绑定一个properties到guice中,当然了,由于properties本质上时一个map,因此guice也允许绑定一个map。
1 @inject
2 @named("web")
3 private string web;
4
5 public static void main(string[] args) {
6
7 constantinjectdemo cid = guice.createinjector(new module() {
8 @override
9 public void configure(binder binder) {
10 properties properties= new properties();
11 properties.setproperty("web", "www.imxylz.cn");
12 names.bindproperties(binder, properties);
13 }
14 }).getinstance(constantinjectdemo.class);
15 system.out.println(cid.web);
16 }
17
18
上一篇:
下一篇:
©2009-2014 imxylz
|求贤若渴