Dagger2 依赖注入之@Inject 分析

Dagger

下面主要分析,Dagger 中使用 @Inject 注解一个构造方法来提供依赖的过程。

举个栗子

老王开车去东北

老王

老王已经拿到驾驶证了,说飙车就能飙车:

  • Person

通过 @Inject 来标注 Person 中需要使用 Car:

public class Person {
    @Inject
    Car car;

    public void goDongbei(){
        car.run();
    }
}

老王借车

老王从老李哪里借了一辆 GTR,两人签了一个借车合约(PersonComponent):

  • PersonComponent

PersonComponent 接口表明需要向 Person 中注入一些依赖:

@Component
public interface PersonComponent {
    void inject(Person person);
}

GTR

  • Car

Car的构造函数使用 @Inject 来提供依赖:

public class Car {
    private static final String TAG = "Car";

    @Inject
    Car(){}
    
    public void run(){
        Log.d(TAG, "run: 一起去东北");
    }
}

三者关系如下:

Car 老王去东北的依赖工具------为依赖的提供者,此处通过 @Inject 标注其构造方法来指明

Person 一个说飙车就飙车的老王-------为依赖的使用者,此处通过 @Inject 标注其要使用的依赖类

PersonComponent 借车合约----------将 Car 提供给 Person 使用,其中 void inject(Person person) 表明需要向 Person 中注入一些依赖。

发动 GTR

此时,build一把工程,然后添加如下代码:

Person person = new Person();
DaggerPersonComponent.builder().build().inject(person);
person.goShopping();

向东北粗发

最后run一把工程,输出如下:

2019-04-17 14:38:13.046 4772-4772/com.example.demo_dagger2 D/Car: run: ~~~~~~

run: 一起去东北

源码分析

那么问题来了,Dagger 怎么凭借 DaggerPersonComponent.builder().build().inject(person) 一个链式调用就把 Car 对象注入到 Person 的呢?

先看看 DaggerPersonComponent 到底是什么?

DaggerPersonComponent 为工程 build 后 Dagger 利用注解自动生成的代码

// Generated by dagger.internal.codegen.ComponentProcessor (https://google.github.io/dagger).
public final class DaggerPersonComponent implements PersonComponent {
  private MembersInjector<Person> personMembersInjector;

  private DaggerPersonComponent(Builder builder) {
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {
    return new Builder();
  }

  public static PersonComponent create() {
    return builder().build();
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.personMembersInjector = Person_MembersInjector.create(Car_Factory.create());
  }

  @Override
  public void inject(Person person) {
    personMembersInjector.injectMembers(person);
  }

  public static final class Builder {
    private Builder() {}

    public PersonComponent build() {
      return new DaggerPersonComponent(this);
    }
  }
}

DaggerPersonComponent类实现了我们的 PersonComponent,其通过构建者模式来创建 DaggerPersonComponent 对象,
在该对象构建过程中会调用 initialize(builder) ,该方法利用 Person_MembersInjector.create 来实例化一个 personMembersInjector 对象,至于 personMembersInjector
到底是干嘛的,后面再说。

所以说调用 DaggerPersonComponent.builder().build() 后,其实就是构建一个 DaggerPersonComponent 对象,然后继续调用其 inject 方法来注入依赖。

把 Inject 方法单独提出来看看:

  @Override
  public void inject(Person person) {
    personMembersInjector.injectMembers(person);
  }

看到这里,我们知道最后的依赖注入其实是 personMembersInjector.injectMembers(person) 来完成的。

Person_MembersInjector 也为 Dagger 为我们生成的代码:

package com.example.demo_dagger2;

public final class Person_MembersInjector implements MembersInjector<Person> {
  private final Provider<Car> carProvider;

  public Person_MembersInjector(Provider<Car> carProvider) {
    assert carProvider != null;
    this.carProvider = carProvider;
  }

  public static MembersInjector<Person> create(Provider<Car> carProvider) {
    return new Person_MembersInjector(carProvider);
  }

  @Override
  public void injectMembers(Person instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.car = carProvider.get();
  }

  public static void injectCar(Person instance, Provider<Car> carProvider) {
    instance.car = carProvider.get();
  }
}

injectMembers 方法中对 person 对象进行car对象的注入。

到这里还有一个疑问,Car 对象何时传入到 Person_MembersInjector 中的呢?

上面说过在构建 DaggerPersonComponent 对象过程中,会调用一个 initialize 方法:

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.personMembersInjector = Person_MembersInjector.create(Car_Factory.create());
  }

其中 Car_Factory.create() 会为我们生产一个 car 对象,然后 Person_MembersInjector 会存储该 car 对象,以待后面的依赖注入。

Car_Factory 也为 Dagger 为我们自动生成的一个类:

// Generated by dagger.internal.codegen.ComponentProcessor (https://google.github.io/dagger).
package com.example.demo_dagger2;

import dagger.internal.Factory;

public final class Car_Factory implements Factory<Car> {
  // 饿汉单例,确保线程安全
  private static final Car_Factory INSTANCE = new Car_Factory();

  @Override
  public Car get() {
    return new Car();
  }

  public static Factory<Car> create() {
    return INSTANCE;
  }

  /** Proxies {@link Car#Car()}. */
  public static Car newCar() {
    return new Car();
  }
}

注入过程

DaggerPersonComponent.builder().build().inject(person)

  1. 构建 DaggerPersonComponent 对象,即调用 DaggerPersonComponent.builder().build() 方法。

    • DaggerPersonComponent 对象是基于构建者模式

    • 在构建 DaggerPersonComponent 对象过程中,也会实例化一个 Person_MembersInjector 对象

    • 在实例化 Person_MembersInjector 对象过程中,会保存 Car 的实例,以待后面的依赖的注入

    • Car 的实例化是通过工厂方法(Car_Factory.create())来完成

    牛逼吧~当我们构建 DaggerPersonComponent 对象中,其实也构建了 Person_MembersInjector 对象和依赖对象 car

  2. 调用 DaggerPersonComponent 对象的inject方法,将 car 注入到 person 中

小结:

依赖对象 car 何时创建

调用 DaggerPersonComponent.builder().build() 方法时,通过工厂方法创建Car对象。

谁负责注入

Person_MembersInjector 负责将 Car 对象注入到需要该依赖的地方

怎么注入

当我们显示调用 DaggerPersonComponent 对象的inject方法时,DaggerPersonComponent 会用 Person_MembersInjector 来注入car对象

依赖提供者和需求者

在此案例中:

  • @injec注释的 Car 构造方法,表明其为一个依赖提供者

  • 在我们的 PersonComponent 接口中定义的 void inject(Person person)方法,表明 Person 为依赖需求者,当然在Person 还需要使用 @Injec 注解其用到的 Car 类型。

展开阅读全文

没有更多推荐了,返回首页