Dagger2 源码分析

Dagger简单介绍

Dagger2涉及到依赖注入,有关依赖注入的请到
理解依赖注入

通过注解方式实现依赖注入分为两种:

  • 在运行时读取注解来实现依赖注入,依赖的生成和注入需要依靠 Java 的反射机制。
  • 通过apt插件在编译阶段生成注入代码。

Dagger2是属于后者,反射只是在编译阶段使用了,而在应用运行的时候其实运行的是真正的Java代码并没有涉及到注解反射。

本文用一个极简的demo来说明Dagger原理,不去结合MVP模式使用Dagger方式,我自己认为这样会更加的复杂。

Dagger编译阶段到底干了什么?

有一个超简单的demo只有三个类分别是:MainActivity、MainComponent和PersonBean。

Dagger2 源码分析_第1张图片
三个类之间的关系

Demo代码

public class PersonBean {

    public String name;

    @Inject
    public PersonBean(){
    }
}
@Component
public interface MainComponent {
    void inject(MainActivity activity);
}

写好PersonBean、MainComponent 代码后,使用as的build->make project,会生成DaggerMainComponent,在MainActivity上使用

public class MainActivity extends AppCompatActivity {

    @Inject
    PersonBean personBean;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        DaggerMainComponent.builder().build().inject(this);
    }
}

上面使用了as的build->make project后,会在app/build/generated/source/apt目录下生成对应的注入代码。

PersonBean - 》 PersonBean_Factory

public enum PersonBean_Factory implements Factory {
  INSTANCE;

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

  public static Factory create() {
    return INSTANCE;
  }
}

通过上面代码直观的看到PersonBean_Factory有两个方法:

  • get()
    在该方法中初始化了目标类需要依赖的PersonBean对象。

  • create()
    在该方法返回了PersonBean_Factory本类的实例。

MainComponent-》DaggerMainComponent

public final class DaggerMainComponent implements MainComponent {
  private MembersInjector mainActivityMembersInjector;

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

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

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

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

    this.mainActivityMembersInjector =
        MainActivity_MembersInjector.create(PersonBean_Factory.create());
  }

  @Override
  public void inject(MainActivity activity) {
    mainActivityMembersInjector.injectMembers(activity);
  }

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

    public MainComponent build() {
      return new DaggerMainComponent(this);
    }
  }
}

通过上面代码直观的看到:

  1. DaggerMainComponent对象是通过设计模式之构造器模式创建的
  2. DaggerMainComponent实现了MainComponent接口并实现了其中的inject()方法。

MainActivity -》MainActivity_MembersInjector

public final class MainActivity_MembersInjector implements MembersInjector {
  private final Provider personBeanProvider;

  public MainActivity_MembersInjector(Provider personBeanProvider) {
    assert personBeanProvider != null;
    this.personBeanProvider = personBeanProvider;
  }

  public static MembersInjector create(Provider personBeanProvider) {
    return new MainActivity_MembersInjector(personBeanProvider);
  }

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

  public static void injectPersonBean(
      MainActivity instance, Provider personBeanProvider) {
    instance.personBean = personBeanProvider.get();
  }
}

这里我们就有一些疑问:
我们通过编译期间生成的这些类

  • 这些类之间的关系是怎样的?
  • 这些类中的方法如何被调用?
  • 一个完成的注入过程是怎么的?

首先第一个问题,这些类之间的关系是怎样的?请看下面的UML类图

Dagger2 源码分析_第2张图片
Dagger的UML类图

上面的第二三疑问,通过接下来分析dagger2依赖注入过程来理解,也就是代码执行流程。

dagger2依赖注入过程

DaggerMainComponent.builder().build().inject(this);

首先我们从这一句代码为切入点,来学习dagger2依赖注入过程。

  1. DaggerMainComponent.builder()
    创建一个DaggerMainComponent内部的Builder对象并返回它。

  2. DaggerMainComponent.builder().build()
    创建一个DaggerMainComponent对象并返回它。这里我们知道DaggerMainComponent对象的实例化是通过构造器模式被创建的。

DaggerMainComponent构造方法

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

private void initialize(final Builder builder) {

    this.mainActivityMembersInjector =
        MainActivity_MembersInjector.create(PersonBean_Factory.create());
  }

DaggerMainComponent构造函数干了这些事情:

  • 调用PersonBean_Factory.create()得到PersonBean_Factory对象,然后把此对象作为参数传入MainActivity_MembersInjector.create(...),然后MainActivity_MembersInjector.create方法创建
    MainActivity_MembersInjector实例对象并赋值,那么
    DaggerMainComponent就关联上了它。

4.DaggerMainComponent.builder().build().inject(this);
实际上是调用DaggerMainComponent.inject方法

 @Override
  public void inject(MainActivity activity) {
    mainActivityMembersInjector.injectMembers(activity);
  }

在这方法中使用在DaggerMainComponent构造方法中注入的MainActivity_MembersInjector对象,并调用其injectMembers方法。

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

instance.personBean = personBeanProvider.get();这段代码很关键,目标类MainActivity依赖的类PersonBean就是在这时候被赋值的。personBeanProvider其实就是PersonBean_Factory。

personBeanProvider.get()代码如下:

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

该方法创建一个被依赖的对象PersonBean并返回。

这里我们就了解了Dagger2的依赖注入过程。

你可能感兴趣的:(Dagger2 源码分析)