Dagger2注入原理简单分析


写在前面

本文适合接触过,或者已经使用了一段dagger2的小伙伴加深印象,或者想要深入的了解关于dagger2如何进入DI(dependencies inject)过程的一个简单的分析,起到抛砖引玉的作用.

如果你还不知道Dagger2是什么的话,建议去Google 百度 一下.这里就不赘述了,好多好多资料..

重点类

  • Provider
  • Factory
  • MembersInjector

前两个接口其实是一个东西. Factory 继承了 Provider 内部只存在1个方法 get();究其根本,从字面意思上理解就是提供者.它们是泛型借口,get()方法的返回值也同样是该泛型.这里我们可以做一下猜测,它返回的应该是需要注入的类.

MembersInjector 同样也是一个接口,内部也是只有一个方法
injectMembers(T instance) 很直白,直面理解就是成员注入,猜测这个的作用是对于目标累的注入,而T则是目标类.


编译后生成的源码路径结构如下

Dagger2注入原理简单分析_第1张图片

编译生成的累并不多.

为了防止迷惑.下面讲简单的贴出dagger2的配置过程,如果小伙伴们对这个配置已经很熟悉的话请忽略下面,直接跳到分析原理的过程

Dagger2注入原理简单分析_第2张图片


AppComponent

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    Context getContext();
}

AppModule

@Module
public class AppModule {

    private Application appContext;

    public AppModule(App app) {
        this.appContext = app;
    }

    @Provides
    @Singleton
    public Context provideContext() {
        return appContext;
    }
}

App

public class App extends Application {

    private static App INSTANCE;
    @Override
    public void onCreate() {
        super.onCreate();
        INSTANCE = this;

    }

    public static AppComponent getAppComponent() {
       AppComponent appComponent =  DaggerAppComponent.builder()
                .appModule(new AppModule(INSTANCE))
                .build();

        return appComponent;
    }
}

ActivityComponent

@ActivityScope
@Component(dependencies = AppComponent.class,modules = ActivityModule.class)
public interface ActivityComponent {

    void inject(MainActivity mainActivity);

}

ActivityModule

@Module
public class ActivityModule {

    private Activity activity;

    public ActivityModule(Activity activity) {
        this.activity = activity;
    }

    @Provides
    @ActivityScope
    public Context provideContext() {
        return activity;
    }

    @Provides
    @ActivityScope
    public Person providePerson() {
        return new Person();
    }
}

MainActivity

public class MainActivity extends AppCompatActivity {

    @Inject Person p;
    private TextView textView;


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

    private void injectActivity() {
        ActivityComponent activityComponent = DaggerActivityComponent
                .builder()
                .appComponent(App.getAppComponent())
                .activityModule(new ActivityModule(this))
                .build();

        activityComponent.inject(this);
    }

    private void initView() {
        textView =(TextView)findViewById(R.id.tv_daggertest);
        textView.setText(p.toString());
    }
}

Person

public class Person {


    private String name = "张三";
    private int age = 26;

    public Person() {
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

代码不多.配置起来也很简单. 运行结果如下
Dagger2注入原理简单分析_第3张图片

好了.下面开始步入正题,证实我们上面的猜测.这里我们直接从Activity的注入开始.因为App种并不需要注入.只需要提供AppComponent

public final class DaggerActivityComponent implements ActivityComponent {
  private Provider providePersonProvider;

  private MembersInjector mainActivityMembersInjector;

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

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

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

    this.providePersonProvider =
        DoubleCheck.provider(ActivityModule_ProvidePersonFactory.create(builder.activityModule));

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

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

  public static final class Builder {
    private ActivityModule activityModule;

    private AppComponent appComponent;

    private Builder() {}

    public ActivityComponent build() {
      if (activityModule == null) {
        throw new IllegalStateException(ActivityModule.class.getCanonicalName() + " must be set");
      }
      if (appComponent == null) {
        throw new IllegalStateException(AppComponent.class.getCanonicalName() + " must be set");
      }
      return new DaggerActivityComponent(this);
    }

    public Builder activityModule(ActivityModule activityModule) {
      this.activityModule = Preconditions.checkNotNull(activityModule);
      return this;
    }

    public Builder appComponent(AppComponent appComponent) {
      this.appComponent = Preconditions.checkNotNull(appComponent);
      return this;
    }
  }
}

这个类是配置后AS编译后生成的.名称是固定的DaggerActivityComponent就是在自定义的 XXXComponent前面加上Dagger ,其实就是他的实现类,实现了你在Component中定义的所有方法,和通常的接口实现类并没有说明去区别.
在它的内部,IDE帮我们生成了下面2个成员变量

  • private Provider providePersonProvider;
  • private MembersInjector mainActivityMembersInjector;

并在构造函数中进行初始化

private void initialize(final Builder builder) {

    this.providePersonProvider =
        DoubleCheck.provider(ActivityModule_ProvidePersonFactory.create(builder.activityModule));

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

在前面也提到了这2个对象的一些作用,一个是提供,一个是注入,
Provider 是提供所需要的Person对象,初始化providePersonProvider后传递到mainActivityMembersInjector种,注入目标类,下面看一下这2个类的具体实现

ActivityModule_ProvidePersonFactory

public final class ActivityModule_ProvidePersonFactory implements Factory<Person> {
  private final ActivityModule module;

  public ActivityModule_ProvidePersonFactory(ActivityModule module) {
    assert module != null;
    this.module = module;
  }

  @Override
  public Person get() {
    return Preconditions.checkNotNull(
        module.providePerson(), "Cannot return null from a non-@Nullable @Provides method");
  }

  public static Factory create(ActivityModule module) {
    return new ActivityModule_ProvidePersonFactory(module);
  }
}

通过Create方法传递对应提供的配置的module注入到类中,然后在get方法种返回得到的Person实例,其实这里调用的module.providePerson()就是在ActivityModule种用@Provider标识的providePerson()方法

MainActivity_MembersInjector

public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  private final Provider pProvider;

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

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

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

  public static void injectP(MainActivity instance, Provider pProvider) {
    instance.p = pProvider.get();
  }
}

因为在DaggerActivityCompon的构造函数中ActivityModule_ProvidePersonFactory的实例已经传递到了mainActivityMembersInjector中,也就是说,其实这两个类已经形成了依赖关系,这里

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

这个方法其实就是给Activity种用@Injcet标识的Person对象进行赋值,这个方法其实就是在DaggerActivityComponent中调用的,这样一来,所有的注入关系,初始化关系就形成了.


到这里.dagger2的注入原理就分析完成了,总结一下

IDE帮助我们生成的以Dagger开头的类,实现了我们自定义的XXXComponent,并在构造方法中初始化了Provider和MembersInjector的实现类的实例,并把Provider的实例传入MembersInjector中,形成依赖关系.然后通过Provider的实现类中的get方法获取自定义的Module中配置的实例,在MembersInjector的injectMembers方法中完成对目标类注入依赖类的初始化工作.

你可能感兴趣的:(Android)