1.3 更多話題
1.3.1 接口多實(shí)現(xiàn)
如果一個(gè)接口有多個(gè)實(shí)現(xiàn),這樣通過@Inject和Module都難以直接實(shí)現(xiàn),但是這種現(xiàn)象確實(shí)是存在的,于是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 }
上面的代碼描述的是一個(gè)Service服務(wù),有WwwService和HomeService兩個(gè)實(shí)現(xiàn),同時(shí)有Www和Home兩個(gè)注解(如果對(duì)注解各個(gè)參數(shù)不明白的需要單獨(dú)去學(xué)習(xí)JAVA
5注解)。好了下面請(qǐng)出我們的主角。
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
此類的結(jié)構(gòu)是注入兩個(gè)Service服務(wù),其中wwwService是注入@Www注解關(guān)聯(lián)的WwwService服務(wù),而homeService是注入@Home注解關(guān)聯(lián)的HomeService服務(wù)。
同樣關(guān)于此結(jié)構(gòu)我們要問幾個(gè)問題。
問題(1)靜態(tài)注入多個(gè)服務(wù)怎么寫?
其實(shí),參照教程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):如果不小心一個(gè)屬性綁定了多個(gè)接口怎么辦?
非常不幸,你將得到類似一下的錯(cuò)誤,也就是說不可以綁定多個(gè)服務(wù)。
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):我太懶了不想寫注解來區(qū)分多個(gè)服務(wù),怎么辦?
程序員都是懶惰的,于是Google幫我們提供了一個(gè)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來標(biāo)注我們的服務(wù)應(yīng)該使用什么樣的注解,當(dāng)然前提是我們已經(jīng)將相應(yīng)的服務(wù)與注解關(guān)聯(lián)起來了。
1.3.2 Provider注入
在教程第一篇中我們提到了可以通過Provider注入一個(gè)服務(wù),這里詳細(xì)說說這種模式。
首先我們需要構(gòu)造一個(gè)Provider<T>出來。
1 public class WwwServiceProvider implements Provider<Service> {
2
3 @Override
4 public Service get() {
5 return new WwwService();
6 }
7 }
8
9
上面的Provider的意思很簡(jiǎn)單,每次新建一個(gè)新的WwwService對(duì)象出來。
注入的過程看下面的代碼。
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來做線程的對(duì)象交換。
當(dāng)然如果想自動(dòng)注入(不使用Module手動(dòng)關(guān)聯(lián))服務(wù)的話,可以使用@ProviderBy注解。
1 @ProvidedBy(WwwServiceProvider.class)
2 public interface Service {
3
4 void execute();
5 }
6
7
這樣我們就不必使用Module將Provider綁定到Service上,獲取服務(wù)就很簡(jiǎn)單了。
ProviderServiceDemo psd = Guice.createInjector().getInstance(ProviderServiceDemo.class);
psd.service.execute();
除了上述兩種方式我們還可以注入Provider,而不是注入服務(wù),比如下面的例子例子中,屬性不再是Service,而是一個(gè)Provider<Service>。
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
當(dāng)然了,由于我們WwwServiceProvider每次都是構(gòu)造一個(gè)新的服務(wù)出來,因此在類ProviderServiceDemo中的provider每次獲取的服務(wù)也是不一樣的。
1.3.3 綁定常量
看看下面的例子,演示了一個(gè)綁定整數(shù)值到實(shí)例的例子。
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
當(dāng)然,既然可以使用Named,也就可以使用自己寫注解了。但是看起來好像沒有多大作用。除了上述寫法,也可以用下面的方式實(shí)現(xiàn)。
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
除了可以綁定基本類型外,還可以綁定一個(gè)Properties到Guice中,當(dāng)然了,由于Properties本質(zhì)上時(shí)一個(gè)Map<String,String>,因此Guice也允許綁定一個(gè)Map<String,String>。
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
上一篇:
Google Guice 入門教程02 - 依賴注入(2)
下一篇:
Google Guice 入門教程04 - 依賴注入(4)©2009-2014 IMXYLZ
|求賢若渴