Google Guice简介
最近看graylog代码,发现使用了google的Guice,几个月前查看es代码也用到guice,还有不记得的好多github开源项目都使用了Google Guice,所以今天简单学习一下Google Guice概念。
Google Guice:
google guice是一个轻量级的依赖注入框架啊,
Guice基本概念:
Guice
: 整个框架的门面Injector
: 一个依赖的管理上下文,负载管理所有的Binder
Binder
: 一个接口和实现的绑定Module
: 一组Binder
Provider
: bean 的提供者Key
:Binder
中对应一个Provider
Scope
:Provider
的作用域
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.class
的 hashcode
和注解的 hashcode
决定了 Key
的 hashcode
,getProvider
时是根据 Key
的 hashcode
来判断是否是同一个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 worldAnother Sending Message + hello world
Google Guice简介相关推荐
- guice google_与Google Guice的动手实践
guice google by Sankalp Bhatia 通过Sankalp Bhatia 与Google Guice的动手实践 (A hands-on session with Google G ...
- Google Guice使用入门
2019独角兽企业重金招聘Python工程师标准>>> 本文通过范例简单地介绍Google Guice的使用,通过下面的范例我们可以知道,Google Guice的使用非常简单. G ...
- Google Guice范例解说之使用入门
http://www.cnblogs.com/xd502djj/archive/2012/06/25/2561414.html Google Guice范例解说之使用入门 http://code.go ...
- 超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享...
超轻量级DI容器框架Google Guice与Spring框架的区别教程详解及其demo代码片段分享 DI框架 Google-Guice入门介绍 转载于:https://www.cnblogs.com ...
- guice 实例_使用Google Guice消除实例之间的歧义
guice 实例 如果接口有多个实现,则Google guice提供了一种精巧的方法来选择目标实现. 我的示例基于Josh Long ( @starbuxman )的出色文章,内容涉及Spring提供 ...
- guice 框架_玩! 框架+ Google Guice
guice 框架 在我目前正在工作的项目中,我们开始使用Google Guice. 对于那些不知道的人, Google Guice是一个依赖项注入框架. 依赖项注入的基本思想是提供一个其依赖的类,而不 ...
- 使用Google Guice消除实例之间的歧义
如果接口有多个实现,则Google guice提供了一种精巧的方法来选择目标实现. 我的示例基于Josh Long ( @starbuxman )的出色文章,内容涉及Spring提供的类似机制. 因此 ...
- 玩! 框架+ Google Guice
在我目前正在工作的项目中,我们开始使用Google Guice. 对于那些不知道的人, Google Guice是一个依赖项注入框架. 依赖项注入背后的基本思想是提供一个它依赖的类,而不是使依赖类负责 ...
- Google Guice 一个轻量级的依赖注入框架
1.美图 2.概述 2.1 背景 在做项目的时候,看见有段代码直接是使用Google Guice 注入了avaitor表达式. 2.1 官网 Github 主页:https://github.com/ ...
- Google Perftools简介与使用
一. 安装与简介 从主页http://code.google.com/p/google-perftools/downloads/list下载源码包,解压后使用命令序列./configure;make; ...
最新文章
- DSP5509项目之用FFT识别钢琴音调(1)
- 锐捷交换机实验案例:vlan间互访的配置与验证
- 什么是SQL Server日志传送?
- STM32开源代码——OLED汉字显示程序
- Python爬取招聘网站岗位信息
- 通过键盘移动鼠标光标 autohotkey
- AUTOCAD使用笔记
- 江城武汉,一座离开后会怀念的城市
- 公众号如何用微信红包吸粉而不被封号?实战24天10万粉
- mysql 保留小数位数
- win10配置apache
- Java笔试题(一)单选题
- horizon 申请证书
- 初学用python写爬虫, 这里分享给大家一段爬取百度贴吧的代码(用面向对象的思想写的),请各位大佬们指点迷津
- springboot操作pdf(一)之word转pdf
- 磁盘分区魔法师Norton PartitionMagic(PQ8.0)使用图解和使用
- 每日一题之 hiho232周 拆字游戏
- DNSPod十问国泰航空郑悦:数字化如何让航司冲上云霄?
- linux上不了网有两个网卡,linux上两个常见的网卡报错
- 我的创作纪念日——创作历程,机缘,与成就