guice工作原理-翻译

启动

Injector创建过程概况

Guice使用配置module创建Injector。如果任意一个阶段出现错误,Injector都会停止创建,并抛出CreationException。

第一阶段:静态构建

Guice解析绑定配置,创建对象,校验配置文件。在这个阶段唯一执行的用户代码是Module.configure()。

这阶段只存在于配置为Stage.TOOL。

第二阶段:注入

在这个阶段,如果有必要,对象会被按方法需要注入。例如,静态注入需要一个Provider实例,那么使用前会完成Provider的注入。如果初始化的对象存在环依赖,则不限定注入顺序。

首先,注入通过requestStaticInjection()的静态注册的类。然后,注入requestInjection()、toInstance()、toProvider()方法参数实例。

第三阶段:预加载单例

如果配置Stage.PRODUCTION,全部单例都会被创建。如果配置Stage.DEVELOPMENT,只有使用asEagerSingleton()配置的绑定会被创建。

绑定原理

Injector是如何解决注入的

Injectory是通过绑定配置module与相关注解实现对象的注入。下面介绍如何解决注入:

1、使用精确绑定

如果绑定配置连接的是另一个配置,则依据另一个绑定算法。

如果配置了一个实例,则返回这个实例。

如果配置指定一个提供者,则返回提供者的实例。

2、询问父Injector

如果Injector存在一个父Injector,则请求父Injector解析绑定关系。如果这样成功,则返回这个实例,否则,继续处理。

3、询问子Injectors

如果任何子Injector已经存在这个绑定,则停止。父Injector会保存一份子Injectors的绑定对象黑名单,而不会保存子Injector的引用。

4、处理Prvoider接口注入

如果类型为Provider<T>,则解析T。如果存在注解,则使用相同的注解。

5、转换常量

如果一个常量字符串使用了相同的注解,并且TypeConverter支持这种类型,则使用已转换的字符串。

6、如果依赖存在一个绑定注解,则停止。

Guice不会为带注解绑定配置创建默认绑定。

7、如果依赖是数组或枚举,则停止。

8、TypeLiteral注入

如果依赖的类型为TypeLiteral<T>,则使用参数中的类型注入值。

9、使用注解

如果依赖带@ImplementBy或@ProviderBy注解,查找并使用引用类型的配置。

10、如果依赖是抽象类或非静态内部类,则停止。

11、带有@Inject或无参数的构建方法

校验全部依赖的类型及父类型:构建方法参数、带有@Inject注解的方法和成员变量

调用构造方法

注入全部对象。先注入父类,再注入子类。

注入全部方法。同上。

注入点

Guice是如何决定注入什么

构造方法注入

当Guice通过构造方法实例化一个类型时,它通过如下规则决定调用哪个构造方法:

1、查找带有@Inject注解的构造方法

如果全部构造方法的注解都是@Inject(optional=true),则返回异常。

如果存在多个带有@Inject的构造方法,则返回异常。

如果构造方法带带有绑定对象的注解(如@Named),则返回异常。

2、查找无参数的构造方法

如果构造方法为private类型,但类不是private,则返回异常。在非私有类中,不带@Inject的私有构造方法是不能被注入的。

如果构造方法带带有绑定对象的注解(如@Named),则返回异常。

3、没有找到合适的构造方法,则返回异常。

注入成员变量及方法

Guice按照一个特定顺序注入。先注入成员变量,然后是方法。对于成员变量,先注入父类再注入子类。方法类似。

注入什么?

1、全部使用toInstance()绑定的值。在Injector创建时候注入。

2、全部使用toProvider(Provider)绑定的Provider。在Injector创建时候注入。

3、全部注册使用requestInjection注入的实例。在Injector创建时候注入。

4、当方法调用时,Injector.injectMember的参数。

5、全部Guice通过可注入构造方法创建的值,在初始化后立即注入。无论scope是什么值,都只注入一次。

Guice注入静态方法和成员变量:

全部通过requestStaticInject注册静态注入的类。

如何注入?

注入成员变量:

1、查找配置,按需要创建绑定对象。如果绑定配置不存在,则报错。

2、通过Provider获取绑定对象。Provider如何工作依赖于客户实现。

3、直接将配置值赋给成员变量。不推荐注入final成员,因为注入的值有可能不被其它线程看到。如果成员变量带@Inject(optional=true)、绑定配置不存在且不能被创建,则略过成员变量的注入。

注入方法:

1、查找绑定配置,按需要创建对象。如果配置不存在,则报错。

2、通过Provider获取绑定对象。Provider如何工作依赖于客户实现。

3、使用绑定配置的值作为参数调用方法。如果方法注入是可选的,并且参数配置不存在且不能创建实例,则略过方法注入。

参考:https://github.com/google/guice/wiki/Bootstrap

猜你喜欢

转载自dongmj.iteye.com/blog/2360170
今日推荐