`

Guice框架-DI(依赖注入细节注入)

阅读更多

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     }

 

 

 

 

上面的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     }

这样我们就不必使用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超轻量级依赖注入

    Guice,全称为Google Guice,是一款由Google开发的轻量级依赖注入(Dependency Injection,简称DI)框架,主要用于简化Java应用的初始化和组件管理。依赖注入是一种设计模式,它可以帮助开发者解耦代码,提高软件的...

    guice-3.0.rar

    Guice是Google开发的一款轻量级的Inversion of Control(IoC)容器,它通过依赖注入(Dependency Injection,DI)来管理对象的生命周期和装配。Guice-3.0是Guice的一个版本,包含了核心库guice-3.0.jar,以及与...

    guice-spring-3.2.3.zip

    Guice是一个轻量级的依赖注入(DI)框架,由Google开发,它允许开发者通过注解来管理对象的创建和依赖关系。而Spring是Java领域广泛使用的全面的企业级应用框架,它同样提供了DI功能,还有AOP(面向切面编程)、事务...

    Java guice3.0轻量级的依赖注入框架 组件

    Java Guice 3.0是一款轻量级的依赖注入(Dependency Injection, DI)框架,它致力于简化Java应用程序的构建过程,让组件之间的依赖关系更加清晰和易于管理。依赖注入是一种设计模式,它允许代码在运行时自动管理和...

    Java on Guice - Developer Day Slides.pdf

    本演示文稿通过对比工厂模式、手动依赖注入以及Guice框架下的依赖注入方式,展示了依赖注入的重要性和Guice带来的便利。通过采用Guice进行依赖注入,可以有效提高代码质量,降低维护成本,并增强系统的可测试性和...

    guice-throwingproviders-3.2.1.zip

    Guice是一款轻量级的依赖注入(DI)框架,它使得在Java应用程序中管理对象的生命周期变得简单。ThrowingProviders允许提供者方法抛出受检异常,这在某些情况下非常有用,比如当初始化对象时可能出现的异常。 描述中...

    Java依赖注入框架Guice2

    Java依赖注入框架Guice2是Google开发的一款轻量级的依赖注入库,它极大地简化了Java应用程序中的对象创建和管理。Guice2以其简洁的API和强大的功能在开发者社区中赢得了广泛的认可。依赖注入(Dependency Injection...

    cbsd-di:依赖注入练习

    依赖注入(Dependency Injection,简称DI)是软件设计模式中的一种...在实际开发中,依赖注入不仅限于Spring框架,还有其他如Guice、PicoContainer等选择,但Spring因其强大的功能和广泛的应用而成为Java开发者的首选。

    guice-servlet-3.1.9.zip

    Guice是一款轻量级的依赖注入(DI)框架,它通过提供一种声明性的方式来管理Java应用中的对象生命周期和依赖关系。Guice-Servlet模块则是Guice框架专门用于Web应用的扩展,它提供了与Servlet容器集成的能力,使得在...

    Robojuice jar 包文件下载(内含guice-2.0-no_aop.jar 和roboguice-1.1.2.jar )

    Guice是一个轻量级的依赖注入(DI)框架,由Google开发。依赖注入是一种设计模式,它允许我们在运行时动态地将对象的依赖关系绑定在一起,而不是在代码中硬编码这些依赖关系。Guice通过提供一种声明性的方式来管理...

    stdlib-guice-hibernate-testing-6.1.2.zip

    2. **Guice框架**:Guice是Google开发的一个轻量级依赖注入(Dependency Injection,DI)框架,它通过注解来定义依赖关系,使得对象的创建和管理变得简单。Guice可以减少硬编码的依赖,提高代码的可测试性和可维护性...

    findbugs-guice-0.5.zip

    Guice是Google推出的一款轻量级的依赖注入(DI)框架,它简化了Java应用程序的构建过程,使得组件之间的依赖关系更加清晰。通过注解,Guice可以自动管理对象的创建、依赖关系的注入,降低了代码间的耦合度,提高了可...

    DI容器框架Google Guice与Spring框架的区别

    这个标题表明我们要探讨的是两种不同的依赖注入(Dependency Injection,简称DI)容器——Google Guice和Spring框架之间的差异。DI是一种设计模式,它帮助开发者在对象之间解耦,使得代码更加灵活、可测试和可维护。...

    Guice与Spring框架的区别.pdf

    Guice框架 Guice是Google开发的轻量级DI容器,主要特点是轻量级、快速、灵活。Guice的主要特性包括: * 轻量级:Guice的jar包只有几百KB,非常小巧,非常适合需要快速开发和部署的项目。 * 灵活性高:Guice提供了...

    ratpack-guice-0.9.8.zip

    Guice则是Google开源的一款依赖注入框架,它的主要目的是简化Java应用程序中的对象创建和管理。依赖注入(DI)是一种设计模式,它允许我们解耦组件,使得代码更加灵活和可测试。Guice通过自动管理和配置对象之间的...

    play-java-compile-di-example.zip_java_play

    Play框架通过Guice库支持编译时DI,Guice是Google提供的一款轻量级依赖注入框架,它在编译期间就能检查依赖关系,从而避免了运行时错误。 编译时DI的优势在于它可以捕获依赖关系的错误更早,即在编译阶段,而不是在...

    google-guice

    谷歌Guice,全名Google Guice,是一款轻量级的依赖注入框架,专为Java 5及更高版本设计。依赖注入(Dependency Injection,简称DI)是一种软件设计模式,旨在降低代码间的耦合度,提高可测试性和可维护性。Guice通过...

    nfsdb-guice-1.0.2.zip

    【标题】"nfsdb-guice-1.0.2.zip" 提供的是一个集成NFSDB(网络文件系统数据库)与Guice框架的版本1.0.2的库。NFSDB是一款高性能、可扩展的分布式数据库系统,而Guice是Google开发的一款轻量级依赖注入框架,用于...

Global site tag (gtag.js) - Google Analytics