Leo's Blog

依赖注入框架 -- Dagger2 基础

前言

dagger2 是解决Android或着Java中依赖注入的一个类库(DI类库)。最近看了一些开源的项目都在使用dagger2,而且有很多对其是甚是推崇,我也蠢蠢欲动。。。在学习dagger2的过程中,我遇到了一下的困惑:

  • dagger2 中的Inject,Component,Module,Provides等等都是什么鬼?有什么作用
  • dagger2 到底有什么魔力,让大家都推崇备至
  • 如何在项目中更好的使用dagger2 ?

在具体的学习过程中,看了好多的博客,有时候感觉挺简单,就那么回事吧,但是真正使用的时候,一脸懵逼了。Component应该怎么用?Module应该放些神马?Scope怎么起到作用域控制?。。。一瞬间怀疑人生。本文将自己对dagger2的理解与大家分享一下,希望能对大家有所帮助。

摘要

Inject,Component,Module,Provides他们是什么? 怎么去理解?各自有什么作用?主要讲解抽象的概念,代码的剖析,后期实践中再说~ 下面请看黑板

小科普

Dagger2 就是通过注解实现依赖注入的一种技术手段。

进入正题

Dagger2 注入框架最重要的就是注解的使用,那么我们先来逐个分析这些东东。

@Inject注解

1
2
3
4
5
6
7
8
9
class A {
@Inject
B b;
}
class B {
@Inject
B(){
}
}

@Inject 注解用来标注目标类依赖的实例以以及被依赖类的构造函数。这样,目标类中依赖的实例与被依赖类的构造函数之间有了一种的联系,茫茫大海中,如何找到相互关联的两个 @Inject注解?

@Component 注解

@Component 是连接目标类依赖的实例和被依赖类构造方法的桥梁,@Component标注的类是接口或者抽象类。既然说它是桥梁,我们来分析一下,它是如何工作的。

  • Component类持有目标类的实例。
  • Component查找目标类中用@Inject注解标注的属性,然后查找该属性对应的用@Inject标注的构造函数。
  • 初始化该属性的实例,并进行赋值。

Component 就像是一个注入器,将目标类依赖的实例注入到目标类中。

Tip:Dagger依赖注入的流程

  1. @Inject 标注目标类中的依赖类
  2. @Inject 标注被依赖类的构造函数
  3. 若依赖类还有依赖类,重复 step1 step2
  4. 调用 Component 的 injectXXX(Object) 方法开始依赖注入。(injectXXX 方法名称是官方推荐。)

@Module 注解

新坑来啦!!!项目中会使用很多的第三方类库,对于这些类库的依赖,我们没有办法去修改,不能将@Inject加入到这些类中。这可如何是好。。。

@Module 应运而生,我们可以将第三方类库封装入Module中,来对第三方库进行封装,当然@Module的功能不止封装第三方库,它的应用场景主要有以下三个:

  • 接口(Interface)是没有构造方法的
  • 第三方库提供的类,构造方法不能被注解
  • 有些类需要灵活选择初始化配置,而不是使用单一的构造方法

Module 其实是一个简单工厂模式,Module里面的方法基本都是创建类示例的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Module
public class ActivityModule {
private Activity mActivity;
public ActivityModule(Activity activity) {
this.mActivity = activity;
}
@Provides
@ActivityScope
public Activity provideActivity() {
return mActivity;
}
}

Module 和 Component 又是如何关联起来呢?

Component的新任务

Component 是注入器,它一段连接目标类,另一端链接被依赖类。之前说到Module类是一个提供类实例的类,所以Component的新职责就是将Module提供的被依赖类示例注入到目标类中。(Component中的modules属性可以把Module加入Component,modules可以加入多个Module)。

引入新问题,Modules 中创建的各种类实例如何注入到目标类中,如何与目标类中@Inject标注的依赖产生关联。

@Provides注解

Module 中创建类实例方法用Provides进行标注,Component 在搜索到目标类中用 @Inject 标注的属性后,Component就会去 Module 中去查找用 Provides 标注的对应的创建类实例方法,实现依赖注入。

总结

Inject,Component,Module,Provides 是dagger2中最基础最核心的知识点。

  • @Inject 用来标注目标类的依赖和被依赖类的构造函数
  • @Component 是一个桥梁,一端是目标类,一端是目标类所依赖的实例。负责依赖注入,同时管理 Module。
  • Module 和 Provides Module是一个简单工厂模式,主要包含创建类示例的方法,这些方法用Provides来标注。