Dagger2注入原理简单分析

原创 2017年01月12日 12:25:57

写在前面

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

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

重点类

  • Provider
  • Factory
  • MembersInjector

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

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


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

这里写图片描述

编译生成的累并不多.

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

这里写图片描述


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 +
                '}';
    }
}

代码不多.配置起来也很简单. 运行结果如下
这里写图片描述

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

public final class DaggerActivityComponent implements ActivityComponent {
  private Provider<Person> providePersonProvider;

  private MembersInjector<MainActivity> 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<Person> providePersonProvider;
  • private MembersInjector<MainActivity> 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> 是提供所需要的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<Person> 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<Person> pProvider;

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

  public static MembersInjector<MainActivity> create(Provider<Person> 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<Person> 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方法中完成对目标类注入依赖类的初始化工作.

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Dagger2从入门到放弃再到恍然大悟

现在Dagger2在项目里用的越来越多了,最近花了些时间学习了一下Dagger2,这篇文章主要帮助理解Dagger2的注入实现过程,如有错误,还请指正!什么是Dagger2Dagger2是Dagger...
  • hsk256
  • hsk256
  • 2016年05月29日 10:12
  • 8063

newInstance参数详解

通过反射创建新的类示例,有两种方式:  Class.newInstance()  Constructor.newInstance()  以下对两种调用方式给以比较说明:  Class....

newInstance() 的参数版本与无参数版本详解

通过反射创建新的类示例,有两种方式:  Class.newInstance()  Constructor.newInstance()  以下对两种调用方式给以比较说明:  Class.ne...
  • fei0724
  • fei0724
  • 2014年09月09日 15:52
  • 3281

Android单排上王者系列之Dagger2注入原理解析

在上篇博客中我们介绍了Dagger2该如何在项目中使用,这篇博客将继续分析Dagger2实现的原理,代码依然采用上篇的代码,看这里。Dagger2的注入原理原理的讲解我们通过小明来带我们学习。小明在看...

Dagger2注入原理

这里根据简单基础的注入来分析一些基础注入的原理。不明白基础的请看上一篇重新认识Dagger2文章 Dagger2是通过apt插件在编译阶段生成相应的注入代码的。在完成上面那个例子Rebuil...

Dagger2 原理分析

Dagger2 使用编译时注解 + APT 实现依赖注入,能带来什么好处呢?一个词:解耦。在项目越来越庞大的时候,Dagger2 就体现出强大之处了...
  • xyh269
  • xyh269
  • 2017年04月05日 21:28
  • 353

简单方法:让你理解什么是依赖注入Dagger2(Dependency Injection简称DI)

No DI : 有DI: 这里是怎样使用了DI: 原本在图1: CoffeMaker(){ this.heater =new ElectircHeater(); this.pump ...

MVP+Dagger2简单例子

  • 2015年08月16日 20:58
  • 86KB
  • 下载

dagger2+MVP模板(简单实现)

  • 2017年04月20日 16:43
  • 22.32MB
  • 下载

Dagger2从使用到原理剖析

有没有像我这种从系统转应用的开发,做系统几乎都不需要跟框架打交道,但是呢,做应用,那这些开源框架就不得不天天见面了。我相信很多都会跟我一样,网上很多Dagger2的文章,但是都云里雾里,似懂非懂,所以...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Dagger2注入原理简单分析
举报原因:
原因补充:

(最多只允许输入30个字)