dagger注入原理

265 阅读2分钟
上篇讲了dagger2的使用,这篇将对具体怎么注入做一个分析。
dagger2采用的是APT技术,在编译期间生成java代码,对于注解而言,有效的避免了运行时注解通过反射解析注解信息而影响效率问题。
下面是apt在编译期间自动生成的文件。

文件名生成的具体规则是:
Component: "Dagger" + 类名
工厂类:类名 + “_” + 方法名 + “Factory”
注入器:类名+"_MembersInjector"
下面做具体的源码分析:
DaggerUserComponet.builder()
        .httpComponet(App.getHttpComponet())
        .userModule(new UserModule(this))
        .build()
        .inject(this);//这一步是做真正的注入
首先在activity进行初始化,DaggerUserComponent需要两个参数,一个是UserModule,另外一个是HttpComponet,这里采用的是Builder的设计模式。
public static Builder builder() {
  return new Builder();
}

public static final class Builder {
  private UserModule userModule;

  private HttpComponet httpComponet;

  private Builder() {}

  public Builder userModule(UserModule userModule) {
    this.userModule = Preconditions.checkNotNull(userModule);
    return this;
  }

  public Builder httpComponet(HttpComponet httpComponet) {
    this.httpComponet = Preconditions.checkNotNull(httpComponet);
    return this;
  }

  public UserComponet build() {
    Preconditions.checkBuilderRequirement(userModule, UserModule.class);
    Preconditions.checkBuilderRequirement(httpComponet, HttpComponet.class);
    return new DaggerUserComponet(userModule, httpComponet);
  }
}
最后调用build(),在build()先做判空处理,然后返回一个UserComponent对象。
下面我们来看怎么得到HttpComponent实例。
.httpComponet(App.getHttpComponet())

httpComponet = DaggerHttpComponet
        .builder()
        .httpModule(new HttpModule())
        .build();
跟上面生成UserComponent对象是一个流程。
//DaggerHttpComponet
private DaggerHttpComponet(HttpModule httpModuleParam) {
  initialize(httpModuleParam);
}

private void initialize(final HttpModule httpModuleParam) {
  this.getOkHttpClientProvider =
      DoubleCheck.provider(HttpModule_GetOkHttpClientFactory.create(httpModuleParam));
}

//HttpModule_GetOkHttpClientFactory
public static HttpModule_GetOkHttpClientFactory create(HttpModule module) {
  return new HttpModule_GetOkHttpClientFactory(module);
}
在DaggerHttpComponet的构造方法中先调用initialize(),initialize()主要是创建一个Provider对象。
重点看
DoubleCheck.provider()
DoubleCheck是用来保证单例的类,因为在HttpComponent类中用@Singleton修饰。
@Singleton
@Component(modules = {HttpModule.class})
public interface HttpComponet {
    OkHttpClient getOkHttpClient();
}

public static , T> Provider provider(P delegate) {
  checkNotNull(delegate);
  if (delegate instanceof DoubleCheck) {
    /* This should be a rare case, but if we have a scoped @Binds that delegates to a scoped
     * binding, we shouldn't cache the value again. */
    return delegate;
  }
  return new DoubleCheck(delegate);
}

@Override
public T get() {
  Object result = instance;
  if (result == UNINITIALIZED) {
    synchronized (this) {
      result = instance;
      if (result == UNINITIALIZED) {
        result = provider.get();
        instance = reentrantCheck(instance, result);
        /* Null out the reference to the provider. We are never going to need it again, so we
         * can make it eligible for GC. */
        provider = null;
      }
    }
  }
  return (T) result;
}
在provider()中,如果传入的对象属于DoubleCheck,则直接返回,如果不是,则new DoubleCheck(delegate)。
DoubleCheck实现Provider接口,重写get()方法。在get()中就是类似双检测模式的单例方法。
最后调用build()创建一个实例。
在activity中最后调用inject()进行真正的注入。
@Override
public void inject(MainActivity mainActivity) {
  injectMainActivity(mainActivity);
}

private MainActivity injectMainActivity(MainActivity instance) {
  MainActivity_MembersInjector.injectApiService_dev(
      instance, UserModule_GetHttpServiceFactory.getHttpService(userModule));
  MainActivity_MembersInjector.injectApiService_release(
      instance, UserModule_GetHttpServiceFactory.getHttpService(userModule));
  MainActivity_MembersInjector.injectUserManager(instance, getUserManager());
  return instance;
}

public static void injectUserManager(MainActivity instance, UserManager userManager) {
  instance.userManager = userManager;
}

private UserManager getUserManager() {
  return UserModule_GetUserManagerFactory.getUserManager(
      userModule, getApiService(), UserModule_GetUserStoreFactory.getUserStore(userModule));
}

public static UserManager getUserManager(
    UserModule instance, ApiService apiService, UserStore userStore) {
  return Preconditions.checkNotNull(
      instance.getUserManager(apiService, userStore),
      "Cannot return null from a non-@Nullable @Provides method");
}

@Provides
public UserManager getUserManager(ApiService apiService,UserStore userStore){
    return new UserManager(apiService,userStore);
}
inject()调用的是injectMainActivity(mainActivity),在injectMainActivity中调用的工厂获取对应的得实例,并且赋值。最后返回activity.这样就把所需要的对象创建出来,并进行初始化,我们就可以在对应的类中进行使用。

dagger的使用:juejin.cn/post/688271…