google guice 入门教程03 -凯发k8网页登录

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

   :: 凯发k8网页登录首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  111 随笔 :: 10 文章 :: 2680 评论 :: 0 trackbacks

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
|求贤若渴
posted on 2009-12-24 19:13 imxylz 阅读(18558) 评论(1)     所属分类: google guice
# re: google guice 入门教程03 - 依赖注入(3) 2013-11-16 10:56
给你提个错误吧 第一个multiinterfaceservicedemo中的service全部是private 下面的demo对象有访问权限 这个不对吧 访问权限应该是public吧  回复  
  


©2009-2014
网站地图