转载

Google 开源的依赖注入库,比 Spring 更小更快!

点击上方“ 搜云库技术团队 ”关注,选择“ 设为星标

回复“ 1024 ”或 “ 面试题 ” 获取 4T架构师 资料

Guice是Google开源的一个依赖注入类库,相比于Spring IoC来说更小更快。Elasticsearch大量使用了Guice,本文简单的介绍下Guice的基本概念和使用方式。

学习目标

1、概述:了解Guice是什么,有什么特点;

2、快速开始:通过实例了解Guice;

3、核心概念:了解Guice涉及的核心概念,如绑定(Binding)、范围(Scope)和注入(Injection);

4、最佳实践:官方推荐的最佳实践;

Guice概述

1、Guice是Google开源的依赖注入类库,通过Guice减少了对工厂方法和new的使用,使得代码更易交付、测试和重用;

2、Guice可以帮助我们更好地设计API,它是个轻量级非侵入式的类库;

3、Guice对开发友好,当有异常发生时能提供更多有用的信息用于分析;

快速开始

假设一个在线预订Pizza的网站,其有一个计费服务接口:

使用new的方式获取信用卡支付处理器和数据库交易日志记录器:

使用new的问题是使得代码耦合,不易维护和测试。比如在UT里不可能直接用真实的信用卡支付,需要Mock一个CreditCardProcessor。相比于new,更容易想到的改进是使用工厂方法,但是工厂方法在测试中仍存在问题(因为通常使用全局变量来保存实例,如果在用例中未重置可能会影响其他用例) 。整编:微信公众号,搜云库技术团队,ID:souyunku

更好的方式是通过构造方法注入依赖:

对于真实的网站应用可以注入真正的业务处理服务类:

而在测试用例中可以注入Mock类:

那通过Guice怎么实现依赖注入呢?首先我们需要告诉Guice如果找到接口对应的实现类,这个可以通过 模块 来实现:

这里的模块只需要实现Module接口或继承自AbstractModule,然后在configure方法中设置 绑定 (后面会继续介绍)即可 。整编:微信公众号,搜云库技术团队,ID:souyunku

然后只需在原有的构造方法中增加@Inject注解即可 注入

最后,再看看main方法中是如何调用的:

绑定

连接绑定

连接绑定是最常用的绑定方式,它将一个类型和它的实现进行映射。下面的例子中将TransactionLog接口映射到它的实现类DatabaseTransactionLog。

连接绑定还支持链式,比如下面的例子最终将TransactionLog接口映射到实现类MySqlDatabaseTransactionLog。

注解绑定

通过一个类型可能存在多个实现,比如在信用卡支付处理器中存在PayPal的支付和Google支付,这样通过连接绑定就搞不定。这时我们可以通过注解绑定来实现:

可以看到在模块的绑定时用annotatedWith方法指定具体的注解来进行绑定,这种方式有一个问题就是我们必须增加自定义的注解来绑定,基于此Guice内置了一个@Named注解满足该场景:

实例绑定

将一个类型绑定到一个具体的实例而非实现类,这个通过是在无依赖的对象(比如值对象)中使用。如果toInstance包含复杂的逻辑会导致启动速度,此时应该通过@Provides方法绑定 。整编:微信公众号,搜云库技术团队,ID:souyunku

@Provides方法绑定

模块中定义的、带有@Provides注解的、方法返回值即为绑定映射的类型。

Provider绑定

如果使用@Provides方法绑定逻辑越来越复杂时就可以通过Provider绑定(一个实现了Provider接口的实现类)来实现。

无目标绑定

当我们想提供对一个具体的类给注入器时就可以采用无目标绑定。

构造器绑定

3.0新增的绑定,适用于第三方提供的类或者是有多个构造器参与依赖注入。通过@Provides方法可以显式调用构造器,但是这种方式有一个限制:无法给这些实例应用AOP。

范围

默认情况下,Guice每次都会返回一个新的实例,这个可以通过范围(Scope)来配置。常见的范围有单例(@Singleton)、会话(@SessionScoped)和请求(@RequestScoped),另外还可以通过自定义的范围来扩展 。整编:微信公众号,搜云库技术团队,ID:souyunku

范围的注解可以应该在实现类、@Provides方法中,或在绑定的时候指定(优先级最高):

另外,Guice还有一种特殊的单例模式叫饥饿单例(相对于懒加载单例来说):

注入

依赖注入的要求就是将行为和依赖分离,它建议将依赖注入而非通过工厂类的方法去查找。注入的方式通常有构造器注入、方法注入、属性注入等。

辅助注入

辅助注入(Assisted Inject)属于Guice扩展的一部分,它通过@Assisted注解自动生成工厂来加强非注入参数的使用。

最佳实践

1、最小化可变性:尽可能注入的是不可变对象;

2、只注入直接依赖:不用注入一个实例来获取真正需要的实例,增加复杂性且不易测试;

3、避免循环依赖

4、避免静态状态:静态状态和可测试性就是天敌;

5、采用@Nullable:Guice默认情况下禁止注入null对象;

6、模块的处理必须要快并且无副作用

7、在Providers绑定中当心IO问题:因为Provider不检查异常、不支持超时、不支持重试;

8、不用在模块中处理分支逻辑

9、尽可能不要暴露构造器

作者:GinoBeFunny

https://zhuanlan.zhihu.com/p/24924391

近期技术热文

1、 郁闷! RabbitMQ和Kafka到底怎么选?  

2、 优化后,ES 做到了几十亿数据检索 3 秒返回!  

3、 微服务为什么使用 Zookeeper 做注册中心?  

4、 Spring Bean生命周期,11 张高清流程图及代码  

5、 Spring Boot+RabbitMQ 保证消息100%投递成功  

6、 Spring Boot+Redis 扛住,瞬间千次重复提交(实例)

Google 开源的依赖注入库,比 Spring 更小更快!

原文  http://mp.weixin.qq.com/s?__biz=MzA3MTUzOTcxOQ==&mid=2452969066&idx=1&sn=5da7af29460221b28744fa912ef65fc2
正文到此结束
Loading...