Dagger2实现依赖注入之深入探究

上一篇文章 Dagger2实现依赖注入之一步一步带你入门已经和大家分享了Dagger2的基本使用,如果你还没学会,可以边看文章边自己操作一遍。

上次说到,第六个步骤需要我们自己去重新编译一下项目,不然是无法执行最后一步的,也就是添加以下代码。
     DaggerPassPortComponent.builder()
                    .applicationComponent(getAppComponent())
                    .passPortModule(new PassPortModule(this))
                    .build()
                    .inject(this);

我们可以看到代码中有个 DaggerPassPortComponent,这个类就是完成依赖关系后重新编译生成的,但是如果编译不过是不会生成这个类的,这里说下,如果在目标类用 @Inject 做了注解的属性但是没有相应地在提供依赖类中写明提供依赖的方法,编译也是不会过的,是不是有点绕,没事,我们看代码。

比如我在 PassPortActivity 中用 @Inject 注解了两个属性,但是我在 PassPortModule 中把 provideIDCard 方法注释掉,那么重新编译之后就会出错。
        @Inject
        IDCardBean mIDCard;

        @Inject
        FamilyRegisterBean mFamilyRegister;

    //    @PerActivity
    //    @Provides
    //    public IDCardBean provideIDCard() {
    //        return new IDCardBean(mView);
    //    }

        @PerActivity
        @Provides
        public FamilyRegisterBean provideFamilyRegister() {
            return new FamilyRegisterBean(mView);
        }







编译成功之后就会生成一个   DaggerPassPortComponent ,那么这是个什么东西呢,我们一步一步看下他的源码,点 builder() 之后看到
    public static Builder builder() {
        return new Builder();
      }

直接就 new 一个 Builder 实例,这个Builder 是他的内部类
     public static final class Builder {
        private PassPortModule passPortModule;

        private ApplicationComponent applicationComponent;

        private Builder() {}

        public PassPortComponent build() {
          if (passPortModule == null) {
            throw new IllegalStateException(PassPortModule.class.getCanonicalName() + " must be set");
          }
          if (applicationComponent == null) {
            throw new IllegalStateException(
                ApplicationComponent.class.getCanonicalName() + " must be set");
          }
          return new DaggerPassPortComponent(this);
        }

        public Builder passPortModule(PassPortModule passPortModule) {
          this.passPortModule = Preconditions.checkNotNull(passPortModule);
          return this;
        }

        public Builder applicationComponent(ApplicationComponent applicationComponent) {
          this.applicationComponent = Preconditions.checkNotNull(applicationComponent);
          return this;
        }
      }



从中也能很清楚看到,里面的 passPortModule 方法可以把你的 Module 传进去,接着再执行 build()方法,这个方法里面先是判空,然后 new 一个 DaggerPassPortComponent实例。
     private DaggerPassPortComponent(Builder builder) {
        assert builder != null;
        initialize(builder);
      }



而 initalize(builder) 中则有以下重要的代码
    this.provideIDCardProvider =
            DoubleCheck.provider(PassPortModule_ProvideIDCardFactory.create(builder.passPortModule));
     
    this.provideFamilyRegisterProvider =
            DoubleCheck.provider(PassPortModule_ProvideFamilyRegisterFactory.create(builder.passPortModule));

    this.passPortActivityMembersInjector =
            PassPortActivity_MembersInjector.create(provideIDCardProvider, provideFamilyRegisterProvider);




可以看出有一个 PassPortModule_ProvideIDCardFactory 和 PassPortModule_ProvideFamilyRegisterFactory,这两个类也是 Dagger2 生成的,点进去 create方法我们可以看到,其实这两个都是生产依赖的工厂类
    public final class PassPortModule_ProvideFamilyRegisterFactory
        implements Factory {
      private final PassPortModule module;

      public PassPortModule_ProvideFamilyRegisterFactory(PassPortModule module) {
        assert module != null;
        this.module = module;
      }

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

      public static Factory create(PassPortModule module) {
        return new PassPortModule_ProvideFamilyRegisterFactory(module);
      }
    }



还有一个 passPortActivityMembersInjector ,create方法也是 new 出一个实例
    public final class PassPortActivity_MembersInjector implements MembersInjector {
     
      private final Provider mIDCardProvider;

      private final Provider mFamilyRegisterProvider;

      public PassPortActivity_MembersInjector(
          Provider mIDCardProvider,
          Provider mFamilyRegisterProvider) {
        assert mIDCardProvider != null;
        this.mIDCardProvider = mIDCardProvider;
        assert mFamilyRegisterProvider != null;
        this.mFamilyRegisterProvider = mFamilyRegisterProvider;
      }

      public static MembersInjector create(Provider mIDCardProvider,
                                                             Provider mFamilyRegisterProvider) {
        
          return new PassPortActivity_MembersInjector(mIDCardProvider, mFamilyRegisterProvider);
      }

      @Override
      public void injectMembers(PassPortActivity instance) {
        if (instance == null) {
          throw new NullPointerException("Cannot inject members into a null reference");
        }
        instance.mIDCard = mIDCardProvider.get();
        instance.mFamilyRegister = mFamilyRegisterProvider.get();
      }

      public static void injectMIDCard(
          PassPortActivity instance, Provider mIDCardProvider) {
        instance.mIDCard = mIDCardProvider.get();
      }

      public static void injectMFamilyRegister(
          PassPortActivity instance, Provider mFamilyRegisterProvider) {
        instance.mFamilyRegister = mFamilyRegisterProvider.get();
      }
    }



上述源码中的 provider 其实就是一个接口,里面只有一个方法 get()
    public interface Provider {

        /**
         * Provides a fully-constructed and injected instance of {@code T}.
         *
         * @throws RuntimeException if the injector encounters an error while
         *  providing an instance. For example, if an injectable member on
         *  {@code T} throws an exception, the injector may wrap the exception
         *  and throw it to the caller of {@code get()}. Callers should not try
         *  to handle such exceptions as the behavior may vary across injector
         *  implementations and even different configurations of the same injector.
         */
        T get();
    }

那么在  DaggerPassPortComponent 调用 inject()方法的时候,实际就是调用  passPortActivityMembersInjector 中的  injectMembers()方法,就是在这步真正实现了依赖注入。
    @Override
      public void injectMembers(PassPortActivity instance) {
        if (instance == null) {
          throw new NullPointerException("Cannot inject members into a null reference");
        }
        instance.mIDCard = mIDCardProvider.get();
        instance.mFamilyRegister = mFamilyRegisterProvider.get();
      }



细心的朋友已经知道,mFamilyRegisterProvider.get() 实际就是  PassPortModule_ProvideFamilyRegisterFactory 中的 get()方法,里面就是你在module里面写的提供依赖的方法。
     @Override
      public FamilyRegisterBean get() {
        return Preconditions.checkNotNull(
            module.provideFamilyRegister(), "Cannot return null from a non-@Nullable @Provides method");
      }



到此为止,Dagger2的依赖注入流程就和大家分享完了,其实生成的代码都比较简单,大家可以自己再去跟一下代码,看完之后你会对Dagger2有更深的了解。



你可能感兴趣的:(Dagger2)