1.3 多接口实现
1.3.1 接口多实现
如果一个接口有多个实现,这样通过@Inject和Module都难以直接实现,但是这种现象确实是存在的,于是Guice提供了其它注入方式来解决此问题。
比如下面的自定义注解。
public interface Service {
void execute();
}
public class HomeService implements Service {
@Override
public void execute() {
System.out.println("home.imxylz.cn");
}
}
public class WwwService implements Service {
@Override
public void execute() {
System.out.println("www.teny32.blog.51cto.com");
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD,PARAMETER})
@BindingAnnotation
public @interface Home {
}
@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD,PARAMETER})
@BindingAnnotation
public @interface Www {
}
上面的代码描述的是一个Service服务,有WwwService和HomeService两个实现,同时有Www和Home两个注解(如果对注解各个参数不明白的需要单独去学习JAVA 5注解)。
好了下面请出我们的主角。
5 package cn.imxylz.study.guice.inject.more;
7 import com.google.inject.Binder;
8 import com.google.inject.Guice;
9 import com.google.inject.Inject;
10 import com.google.inject.Module;
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) {
binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class);
binder.bind(Service.class).annotatedWith(Home.class).to(HomeService.class);
}}).getInstance(MultiInterfaceServiceDemo.class);
31 misd.homeService.execute();
32 misd.wwwService.execute();
33 }
34 }
此类的结构是注入两个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) {
binder.bind(Service.class).annotatedWith(Www.class).to(WwwService.class);
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) {
binder.bind(Service.class).annotatedWith(Names.named("Www")).to(WwwService.class);
binder.bind(Service.class).annotatedWith(Names.named("Home")).to(HomeService.class);
binder.requestStaticInjection(NoAnnotationMultiInterfaceServiceDemo.class);
15 }
16 });
17 NoAnnotationMultiInterfaceServiceDemo.homeService.execute();
18 NoAnnotationMultiInterfaceServiceDemo.wwwService.execute();
19 }
20 }
上面的例子中我们使用Named来标注我们的服务应该使用什么样的注解,当然前提是我们已经将相应的服务与注解关联起来了。
1.3.2 Provider注入
在教程第一篇中我们提到了可以通过Provider注入一个服务,这里详细说说这种模式。
首先我们需要构造一个Provider<T>出来。
1 public class WwwServiceProvider implements Provider<Service> {
3 @Override
4 public Service get() {
5 return new WwwService();
6 }
7 }
8
9
上面的Provider的意思很简单,每次新建一个新的WwwService对象出来。
注入的过程看下面的代码。
1 public class ProviderServiceDemo {
3 @Inject
4 private Service service;
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 }
17 }
很显然如果这东西和线程绑定就非常好了,比如我们可以使用ThreadLocal来做线程的对象交换。
当然如果想自动注入(不使用Module手动关联)服务的话,可以使用@ProviderBy注解。
1 @ProvidedBy(WwwServiceProvider.class)
2 public interface Service {
4 void execute();
5 }
6
7
这样我们就不必使用Module将Provider绑定到Service上,获取服务就很简单了。
ProviderServiceDemo psd = Guice.createInjector().getInstance(ProviderServiceDemo.class);
psd.service.execute();
除了上述两种方式我们还可以注入Provider,而不是注入服务,比如下面的例子例子中,属性不再是Service,而是一个Provider<Service>。
1 public class ProviderServiceDemo {
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 }
当然,既然可以使用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<String,String>,因此Guice也允许绑定一个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.teny32.blog.51cto.com");
12 Names.bindProperties(binder, properties);
13 }
14 }).getInstance(ConstantInjectDemo.class);
15 System.out.println(cid.web);
16 }
17
18
相关推荐
Guice,全称为Google Guice,是一款由Google开发的轻量级依赖注入(Dependency Injection,简称DI)框架,主要用于简化Java应用的初始化和组件管理。依赖注入是一种设计模式,它可以帮助开发者解耦代码,提高软件的...
Guice是Google开发的一款轻量级的Inversion of Control(IoC)容器,它通过依赖注入(Dependency Injection,DI)来管理对象的生命周期和装配。Guice-3.0是Guice的一个版本,包含了核心库guice-3.0.jar,以及与...
Guice是一个轻量级的依赖注入(DI)框架,由Google开发,它允许开发者通过注解来管理对象的创建和依赖关系。而Spring是Java领域广泛使用的全面的企业级应用框架,它同样提供了DI功能,还有AOP(面向切面编程)、事务...
Java Guice 3.0是一款轻量级的依赖注入(Dependency Injection, DI)框架,它致力于简化Java应用程序的构建过程,让组件之间的依赖关系更加清晰和易于管理。依赖注入是一种设计模式,它允许代码在运行时自动管理和...
本演示文稿通过对比工厂模式、手动依赖注入以及Guice框架下的依赖注入方式,展示了依赖注入的重要性和Guice带来的便利。通过采用Guice进行依赖注入,可以有效提高代码质量,降低维护成本,并增强系统的可测试性和...
Guice是一款轻量级的依赖注入(DI)框架,它使得在Java应用程序中管理对象的生命周期变得简单。ThrowingProviders允许提供者方法抛出受检异常,这在某些情况下非常有用,比如当初始化对象时可能出现的异常。 描述中...
Java依赖注入框架Guice2是Google开发的一款轻量级的依赖注入库,它极大地简化了Java应用程序中的对象创建和管理。Guice2以其简洁的API和强大的功能在开发者社区中赢得了广泛的认可。依赖注入(Dependency Injection...
依赖注入(Dependency Injection,简称DI)是软件设计模式中的一种...在实际开发中,依赖注入不仅限于Spring框架,还有其他如Guice、PicoContainer等选择,但Spring因其强大的功能和广泛的应用而成为Java开发者的首选。
Guice是一款轻量级的依赖注入(DI)框架,它通过提供一种声明性的方式来管理Java应用中的对象生命周期和依赖关系。Guice-Servlet模块则是Guice框架专门用于Web应用的扩展,它提供了与Servlet容器集成的能力,使得在...
Guice是一个轻量级的依赖注入(DI)框架,由Google开发。依赖注入是一种设计模式,它允许我们在运行时动态地将对象的依赖关系绑定在一起,而不是在代码中硬编码这些依赖关系。Guice通过提供一种声明性的方式来管理...
2. **Guice框架**:Guice是Google开发的一个轻量级依赖注入(Dependency Injection,DI)框架,它通过注解来定义依赖关系,使得对象的创建和管理变得简单。Guice可以减少硬编码的依赖,提高代码的可测试性和可维护性...
Guice是Google推出的一款轻量级的依赖注入(DI)框架,它简化了Java应用程序的构建过程,使得组件之间的依赖关系更加清晰。通过注解,Guice可以自动管理对象的创建、依赖关系的注入,降低了代码间的耦合度,提高了可...
这个标题表明我们要探讨的是两种不同的依赖注入(Dependency Injection,简称DI)容器——Google Guice和Spring框架之间的差异。DI是一种设计模式,它帮助开发者在对象之间解耦,使得代码更加灵活、可测试和可维护。...
Guice框架 Guice是Google开发的轻量级DI容器,主要特点是轻量级、快速、灵活。Guice的主要特性包括: * 轻量级:Guice的jar包只有几百KB,非常小巧,非常适合需要快速开发和部署的项目。 * 灵活性高:Guice提供了...
Guice则是Google开源的一款依赖注入框架,它的主要目的是简化Java应用程序中的对象创建和管理。依赖注入(DI)是一种设计模式,它允许我们解耦组件,使得代码更加灵活和可测试。Guice通过自动管理和配置对象之间的...
Play框架通过Guice库支持编译时DI,Guice是Google提供的一款轻量级依赖注入框架,它在编译期间就能检查依赖关系,从而避免了运行时错误。 编译时DI的优势在于它可以捕获依赖关系的错误更早,即在编译阶段,而不是在...
谷歌Guice,全名Google Guice,是一款轻量级的依赖注入框架,专为Java 5及更高版本设计。依赖注入(Dependency Injection,简称DI)是一种软件设计模式,旨在降低代码间的耦合度,提高可测试性和可维护性。Guice通过...
【标题】"nfsdb-guice-1.0.2.zip" 提供的是一个集成NFSDB(网络文件系统数据库)与Guice框架的版本1.0.2的库。NFSDB是一款高性能、可扩展的分布式数据库系统,而Guice是Google开发的一款轻量级依赖注入框架,用于...