最近看graylog代码,发现使用了google的Guice,几个月前查看es代码也用到guice,还有不记得的好多github开源项目都使用了Google Guice,所以今天简单学习一下Google Guice概念。

Google Guice:

google guice是一个轻量级的依赖注入框架啊,

Guice基本概念:

  • Guice:                      整个框架的门面
  • Injector:                一个依赖的管理上下文,负载管理所有的Binder
  • Binder:                    一个接口和实现的绑定
  • Module:                    一组 Binder
  • Provider:                 bean 的提供者
  • KeyBinder               中对应一个 Provider
  • ScopeProvider        的作用域

Guice数据结构,根据Module 创建Injector

public final class Guice {private Guice() {}public static Injector createInjector(Module... modules) {return createInjector((Iterable)Arrays.asList(modules));}public static Injector createInjector(Iterable<? extends Module> modules) {return createInjector(Stage.DEVELOPMENT, modules);}public static Injector createInjector(Stage stage, Module... modules) {return createInjector(stage, (Iterable)Arrays.asList(modules));}public static Injector createInjector(Stage stage, Iterable<? extends Module> modules) {return (new InternalInjectorCreator()).stage(stage).addModules(modules).build();}
}

Injector: 获取binding, provider, T实例

public interface Injector {void injectMembers(Object var1);<T> MembersInjector<T> getMembersInjector(TypeLiteral<T> var1);<T> MembersInjector<T> getMembersInjector(Class<T> var1);Map<Key<?>, Binding<?>> getBindings();Map<Key<?>, Binding<?>> getAllBindings();<T> Binding<T> getBinding(Key<T> var1);<T> Binding<T> getBinding(Class<T> var1);<T> Binding<T> getExistingBinding(Key<T> var1);<T> List<Binding<T>> findBindingsByType(TypeLiteral<T> var1);<T> Provider<T> getProvider(Key<T> var1);<T> Provider<T> getProvider(Class<T> var1);<T> T getInstance(Key<T> var1);<T> T getInstance(Class<T> var1);Injector getParent();Injector createChildInjector(Iterable<? extends Module> var1);Injector createChildInjector(Module... var1);Map<Class<? extends Annotation>, Scope> getScopeBindings();Set<TypeConverterBinding> getTypeConverterBindings();
}

每个绑定 Binding<T> 的结构如下:

public interface Binding<T> extends Element {Key<T> getKey();Provider<T> getProvider();

同时它继承了 Element,里面包含了 Source:

public interface Element {Object getSource();

可以看出每个绑定 Binding<T>,包含一个键 Key<T> 和 一个提供者 Provider

对于每一个提供者 Provider,它提供所需类型的实例:

  • 你可以提供一个类,Guice 会帮你创建它的实例。
  • 你也可以给 Guice 一个你要绑定的类的实例。
  • 你还可以实现你自己的 Provider<T>,Guice 可以向其中注入依赖关系。

每个绑定还有一个可选的作用域。缺省情况下绑定没有作用域,Guice 为每一次注入创建一个新的对象。一个定制的作用域可以使你控制 Guice 是否创建新对象。例如,你可以使用 为每一个 HttpSession 创建一个实例。

injector.getInstance(XXX.class); 的过程:
先根据指定的类来 new Key()Key 包括类信息 XXX.class 和注解信息,XXX.classhashcode 和注解的 hashcode 决定了 KeyhashcodegetProvider 时是根据 Keyhashcode 来判断是否是同一个Key,然后取到 Provider,由 Provider 提供最终的示例。

Google Guice 示例:

添加 Maven 的依赖:

<dependency><groupId>com.google.inject</groupId><artifactId>guice</artifactId><version>4.0</version>
</dependency>

我们首先定义 Communicator 接口,和它的一个实现类 DefaultCommunicatorImpl

public interface Communicator {boolean sendMessage(String message);
}
public class DefaultCommunicatorImpl implements Communicator {public boolean sendMessage(String message) {System.out.println("Sending Message + " + message);return true;}
}

随后我们通过 @Inject 注解来在 Communication 类中注入 Communicator 类的依赖:

import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;import java.util.logging.Logger;public class Communication {@Injectprivate Communicator communicator;public Communication(Boolean keepRecords) {if (keepRecords) {System.out.println("Message logging enabled");}}public boolean sendMessage(String message) {communicator.sendMessage(message);return true;}public static void main(String[] args) {Injector injector = Guice.createInjector(new BasicModule());Communication comms = injector.getInstance(Communication.class);comms.sendMessage("hello world");}
}

main() 中,可以看到我们通过 Injector 得到了一个 Communication 实例,随后调用了 sendMessage() 方法。

那么 BasicModule 类又是怎么样的呢?

The Module is the basic unit of definition of bindings. 定义依赖绑定的基本单元。

  • 它需要继承 AbstractModule
  • 它将 Communication 绑定了到一个实例 Instance,传入参数 true 到构造方法
  • 它将 Communicator 绑定了到一个具体的实现 DefaultCommunicatorImpl
import com.google.inject.AbstractModule;public class BasicModule extends AbstractModule {@Overrideprotected void configure() {// 表明:当需要 Communicator 这个变量时,我们注入 DefaultCommunicatorImpl 的实例作为依赖bind(Communicator.class).to(DefaultCommunicatorImpl.class);bind(Communication.class).toInstance(new Communication(true));}
}

运行输出如下:

Message logging enabled
Sending Message + hello world

我们也可通过 @Provides 注解来在 BasicModule 中定义依赖:

public class BasicModule extends AbstractModule {@Overrideprotected void configure() {bind(Communication.class).toInstance(new Communication(true));}@Provides@Singletonpublic Communicator getCommunicator() {return new DefaultCommunicatorImpl();}
}

其中 @Singleton 注解表明这个依赖的 Scope 是单例,它是延时加载的 lazily initiated。

如果我们对一个依赖进行了多次绑定,例如:

@Provides
@Singleton
public Communicator getCommunicator() {return new DefaultCommunicatorImpl();
}@Provides
@Singleton
public Communicator getCommunicatorOneMoreTime() {return new DefaultCommunicatorImpl();
}

运行时会抛出如下的异常:

1) A binding to demo.guice.Communicator was already configured at demo.guice.BasicModule.getCommunicator().at demo.guice.BasicModule.getCommunicator(BasicModule.java:17)1 errorat com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:466)at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)at com.google.inject.Guice.createInjector(Guice.java:96)at com.google.inject.Guice.createInjector(Guice.java:73)at com.google.inject.Guice.createInjector(Guice.java:62)

假如我们现在有了 Communicator 接口的另外一种实现 AnotherCommunicatorImpl

public class AnotherCommunicatorImpl implements Communicator {public boolean sendMessage(String message) {System.out.println("Another Sending Message + " + message);return true;}
}

同时我们在 Communication 类中需要同时依赖于原有的 DefaultCommunicatorImpl 和新定义的 AnotherCommunicatorImpl,例如:

public class Communication {@Injectprivate Communicator communicator;@Injectprivate Communicator anotherCommunicator;public Communication(Boolean keepRecords) {if (keepRecords) {System.out.println("Message logging enabled");}}public boolean sendMessage(String message) {communicator.sendMessage(message);anotherCommunicator.sendMessage(message);return true;}public static void main(String[] args) {Injector injector = Guice.createInjector(new BasicModule());Communication comms = injector.getInstance(Communication.class);comms.sendMessage("hello world");}
}

那么我们在 BasicModule 应该怎么定义这种绑定呢?
如果我们尝试添加另外一个 @Provides 方法,返回 AnotherCommunicatorImpl,例如:

@Provides
@Singleton
public Communicator getCommunicator() {return new DefaultCommunicatorImpl();
}@Provides
@Singleton
public Communicator getAnotherCommunicator() {return new AnotherCommunicatorImpl();
}

则会有如下的异常:

Exception in thread "main" com.google.inject.CreationException: Unable to create injector, see the following errors:1) A binding to demo.guice.Communicator was already configured at demo.guice.BasicModule.getCommunicator().at demo.guice.BasicModule.getAnotherCommunicator(BasicModule.java:23)

这里我们需要通过 @Named 注解提供为属性赋值的功能。
首先在注入绑定的时候使用 @Named 注解:

@Inject
@Named("communicator")
private Communicator communicator;@Inject
@Named("anotherCommunicator")
private Communicator anotherCommunicator;

随后在定义绑定的时候使用 @Named 注解:

@Provides
@Singleton
@Named("communicator")
public Communicator getCommunicator() {return new DefaultCommunicatorImpl();
}@Provides
@Singleton
@Named("anotherCommunicator")
public Communicator getAnotherCommunicator() {return new AnotherCommunicatorImpl();
}

运行结果如下:

Message logging enabled
Sending Message + hello world

Another Sending Message + hello world

Google Guice简介相关推荐

  1. guice google_与Google Guice的动手实践

    guice google by Sankalp Bhatia 通过Sankalp Bhatia 与Google Guice的动手实践 (A hands-on session with Google G ...

  2. Google Guice使用入门

    2019独角兽企业重金招聘Python工程师标准>>> 本文通过范例简单地介绍Google Guice的使用,通过下面的范例我们可以知道,Google Guice的使用非常简单. G ...

  3. Google Guice范例解说之使用入门

    http://www.cnblogs.com/xd502djj/archive/2012/06/25/2561414.html Google Guice范例解说之使用入门 http://code.go ...

  4. 超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享...

    超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享 DI框架 Google-Guice入门介绍 转载于:https://www.cnblogs.com ...

  5. guice 实例_使用Google Guice消除实例之间的歧义

    guice 实例 如果接口有多个实现,则Google guice提供了一种精巧的方法来选择目标实现. 我的示例基于Josh Long ( @starbuxman )的出色文章,内容涉及Spring提供 ...

  6. guice 框架_玩! 框架+ Google Guice

    guice 框架 在我目前正在工作的项目中,我们开始使用Google Guice. 对于那些不知道的人, Google Guice是一个依赖项注入框架. 依赖项注入的基本思想是提供一个其依赖的类,而不 ...

  7. 使用Google Guice消除实例之间的歧义

    如果接口有多个实现,则Google guice提供了一种精巧的方法来选择目标实现. 我的示例基于Josh Long ( @starbuxman )的出色文章,内容涉及Spring提供的类似机制. 因此 ...

  8. 玩! 框架+ Google Guice

    在我目前正在工作的项目中,我们开始使用Google Guice. 对于那些不知道的人, Google Guice是一个依赖项注入框架. 依赖项注入背后的基本思想是提供一个它依赖的类,而不是使依赖类负责 ...

  9. Google Guice 一个轻量级的依赖注入框架

    1.美图 2.概述 2.1 背景 在做项目的时候,看见有段代码直接是使用Google Guice 注入了avaitor表达式. 2.1 官网 Github 主页:https://github.com/ ...

  10. Google Perftools简介与使用

    一. 安装与简介 从主页http://code.google.com/p/google-perftools/downloads/list下载源码包,解压后使用命令序列./configure;make; ...

最新文章

  1. DSP5509项目之用FFT识别钢琴音调(1)
  2. 锐捷交换机实验案例:vlan间互访的配置与验证
  3. 什么是SQL Server日志传送?
  4. STM32开源代码——OLED汉字显示程序
  5. Python爬取招聘网站岗位信息
  6. 通过键盘移动鼠标光标 autohotkey
  7. AUTOCAD使用笔记
  8. 江城武汉,一座离开后会怀念的城市
  9. 公众号如何用微信红包吸粉而不被封号?实战24天10万粉
  10. mysql 保留小数位数
  11. win10配置apache
  12. Java笔试题(一)单选题
  13. horizon 申请证书
  14. 初学用python写爬虫, 这里分享给大家一段爬取百度贴吧的代码(用面向对象的思想写的),请各位大佬们指点迷津
  15. springboot操作pdf(一)之word转pdf
  16. 磁盘分区魔法师Norton PartitionMagic(PQ8.0)使用图解和使用
  17. 每日一题之 hiho232周 拆字游戏
  18. DNSPod十问国泰航空郑悦:数字化如何让航司冲上云霄?
  19. linux上不了网有两个网卡,linux上两个常见的网卡报错
  20. 我的创作纪念日——创作历程,机缘,与成就

热门文章

  1. c语言小球消砖块增加一行砖块,基于Unity的小球撞击砖块小游戏
  2. 英文词典 text 文本格式下载
  3. rapidminer decision tree(决策树)手册
  4. Linux/Ubuntu20 安装 TP-link(RTL8812AU) 无线网卡驱动
  5. EGE基础:键盘输入篇
  6. 应用程序无法正常启动0xc0150002怎么解决
  7. python半自动化获取QQ空间说说
  8. 英特尔固态盘加速云与大数据应用创新
  9. 四川大学本科教务系统 - 一键评教
  10. IEEE1284 USB转并口打印线缆配置