浅谈Dagger2依赖注入框架

来源:互联网 发布:酒店点菜软件 编辑:程序博客网 时间:2024/05/21 12:46

前言

在讲解Dagger之前,首先要先了解下面这两个概念

  • 什么是依赖注入

    简单的说,就是目标类(目标类需要进行依赖初始化的类,下面都会用目标类一词来指代)中所依赖的其他的类的初始化过程,不是通过手动编码的方式创建,而是通过技术手段可以把其他的类的已经初始化好的实例自动注入到目标类中。
    这里写图片描述

  • Java中注解(Annotation)

    不熟悉这部分知识的同学可以参考我之前写的一篇文章
    Java编程之Annotation全解析

了解完前面的这两个概念,我们接着就来一步步的剖析它

什么是inject

首先先观察一下下面这段代码

class A{       B b = new B(...);       C c = new C();       D d = new D(new E());       F f = new F(.....); }

正如你所看到的那样,上述代码并没有什么逻辑上的问题,可仔细观察不难发现,上述代码很臃肿,存在很多重复性的代码,这时我们就可以考虑用一种自动化的工具来解决这个问题,提高开发效率,把精力集中在重要的业务上。

我们可以用注解(Annotation)来标注目标类中所依赖的其他类,同样用注解来标注所依赖的其他类的构造函数,那注解的名字就叫Inject

class A{        @Inject        B b;   }   class B{       @Inject       B(){       }   }

这样我们就可以让目标类中所依赖的其他类与其他类的构造函数之间有了一种无形的联系。但是要想使它们之间产生直接的关系,还得需要一个桥梁来把它们之间连接起来。那这个桥梁就是Component了。
这里写图片描述

那么什么是Component

Component也是一个注解类,一个类要想是Component,必须用Component注解来标注该类,并且该类是接口或抽象类。我们不讨论具体类的代码,我想从抽象概念的角度来讨论Component。上文中提到Component在目标类中所依赖的其他类与其他类的构造函数之间可以起到一个桥梁的作用。
那我们看看这桥梁是怎么工作的:
Component需要引用到目标类的实例,Component会查找目标类中用Inject注解标注的属性,查找到相应的属性后会接着查找该属性对应的用Inject标注的构造函数(这时候就发生联系了),剩下的工作就是初始化该属性的实例并把实例进行赋值。因此我们也可以给Component叫另外一个名字注入器(Injector)

这里写图片描述

简单总结一下上面的关系

目标类想要初始化自己依赖的其他类:

  • 用Inject注解标注目标类中其他类
  • 用Inject注解标注其他类的构造函数
  • 若其他类还依赖于其他的类,则重复进行上面2个步骤
  • 调用Component(注入器)的injectXXX(Object)方法开始注入(injectXXX方法名字是官方推荐的名字,以inject开始)
  • Component现在是一个注入器,就像注射器一样,Component会把目标类依赖的实例注入到目标类中,来初始化目标类中的依赖。

什么是module

现在有个新问题:项目中使用到了第三方的类库,第三方类库又不能修改,所以根本不可能把Inject注解加入这些类中,这时我们的Inject就失效了。

那我们可以封装第三方的类库,封装的代码怎么管理呢,总不能让这些封装的代码散落在项目中的任何地方,总得有个好的管理机制,那Module就可以担当此任。
可以把封装第三方类库的代码放入Module中,像下面的例子:

 @Module    public class ModuleClass{          //A是第三方类库中的一个类          A provideA(){               return A();          }    }

Module其实是一个简单工厂模式,Module里面的方法基本都是创建类实例的方法。接下来问题来了,因为Component是注入器(Injector),我们怎么能让Component与Module有联系呢?

Component的新职责

Component是注入器,它一端连接目标类,另一端连接目标类依赖实例,它把目标类依赖实例注入到目标类中。上文中的Module是一个提供类实例的类,所以Module应该是属于Component的实例端的(连接各种目标类依赖实例的端),Component的新职责就是管理好Module,Component中的modules属性可以把Module加入Component,modules可以加入多个Module。

这里写图片描述

那接下来的问题是怎么把Module中的各种创建类的实例方法与目标类中的用Inject注解标注的依赖产生关联,那Provides注解就该登场了。

Provides最终解决第三方类库依赖注入问题

Module中的创建类实例方法用Provides进行标注,Component在搜索到目标类中用Inject注解标注的属性后,Component就会去Module中去查找用Provides标注的对应的创建类实例方法,这样就可以解决第三方类库用dagger2实现依赖注入了。

总结

Inject,Component,Module,Provides是dagger2中的最基础最核心的知识点。奠定了dagger2的整个依赖注入框架。
Inject主要是用来标注目标类的依赖和依赖的构造函数
Component它是一个桥梁,一端是目标类,另一端是目标类所依赖类的实例,它也是注入器(Injector)负责把目标类所依赖类的实例注入到目标类中,同时它也管理Module。
Module和Provides是为解决第三方类库而生的,Module是一个简单工厂模式,Module可以包含创建类实例的方法,这些方法用Provides来标注
这里写图片描述

原创粉丝点击