dagger2的生成源碼簡單分析

dagger2官方GitHub: 點擊打開鏈接

直接上圖,自己對dagger2構架的見解:


這裏使用的是官方的實例分析的.

 並稍微修改了CoffeeApp

@Singleton
@Component(modules = {DripCoffeeModule.class})
public interface CoffeeApp {


		void inject(App coffeeApp);
		CoffeeMaker maker();

}

然後生成 :


CoffeeApp會被編譯器生成如下代碼:

public final class DaggerCoffeeApp implements CoffeeApp {
  private Provider<Heater> provideHeaterProvider;

  private Provider<Thermosiphon> thermosiphonProvider; //持有各個提供者

  private Provider<Pump> providePumpProvider;

  private Provider<CoffeeMaker> provideMakerProvider;

  private DaggerCoffeeApp(Builder builder) {
    assert builder != null;
    initialize(builder); //在這裏對提供者或者對類注入器初始化
  }

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

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

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

    this.provideHeaterProvider =
        DoubleCheck.provider(
            DripCoffeeModule_ProvideHeaterFactory.create(builder.dripCoffeeModule));

    this.thermosiphonProvider = Thermosiphon_Factory.create(provideHeaterProvider);

    this.providePumpProvider = (Provider) thermosiphonProvider;

    this.provideMakerProvider =
        DripCoffeeModule_ProvideMakerFactory.create(
            builder.dripCoffeeModule, provideHeaterProvider, providePumpProvider);
  }

  @Override
  public void inject(App coffeeApp) {

//空實現,類似空指針模式.
    MembersInjectors.<App>noOp().injectMembers(coffeeApp);
  }

  @Override
  public CoffeeMaker maker() {
    return provideMakerProvider.get();
  }
	//構建component需要的參數
  public static final class Builder {
    private DripCoffeeModule dripCoffeeModule;

    private Builder() {}

    public CoffeeApp build() {

	//看看這裏就知道你可以傳遞module也可以不傳了吧
      if (dripCoffeeModule == null) {
        this.dripCoffeeModule = new DripCoffeeModule();
      }
      return new DaggerCoffeeApp(this);
    }

    public Builder dripCoffeeModule(DripCoffeeModule dripCoffeeModule) {
      this.dripCoffeeModule = Preconditions.checkNotNull(dripCoffeeModule);
      return this;
    }
  }
}

DaggerCoffeeApp的作用:對module,提供者和類注入器(現在還沒有)進行初始化,也是一個交互的場所.

然後根據module 提供的實例的方法生成 DripCoffeeModule_ProvideHeaterFactory,DripCoffeeModule_ProvideMakerFactory類,上面的xxx_mmmFactory就是指這樣的了,而通過@inject構造注入將生成類名_Factory工廠類:Thermosiphon_Factory ,Person_Factory.

DripCoffeeModule_ProvideHeaterFactory 代碼如下:

public final class DripCoffeeModule_ProvideHeaterFactory implements Factory<Heater> {
  private final DripCoffeeModule module;
	//這裏是通過module來提供實例,所以將持有module實例
  public DripCoffeeModule_ProvideHeaterFactory(DripCoffeeModule module) {
    assert module != null;
    this.module = module;
  }

  @Override
  public Heater get() {

//看到沒有,會調用module的方法,但是provideHeater最終還是調用new 對象()...所以建議使用@inject構造比他效率高
    return Preconditions.checkNotNull(
        module.provideHeater(), "Cannot return null from a non-@Nullable @Provides method");
  }

  public static Factory<Heater> create(DripCoffeeModule module) {
    return new DripCoffeeModule_ProvideHeaterFactory(module);
  }

Thermosiphon_Factory 代碼如下:

public final class Thermosiphon_Factory implements Factory<Thermosiphon> {
  private final Provider<Heater> heaterProvider;

  public Thermosiphon_Factory(Provider<Heater> heaterProvider) {
    assert heaterProvider != null;
    this.heaterProvider = heaterProvider;
  }

  @Override
  public Thermosiphon get() {

	//看到沒有,@inject注入直接調用new 對象();
    return new Thermosiphon(heaterProvider.get());
  }

  public static Factory<Thermosiphon> create(Provider<Heater> heaterProvider) {
    return new Thermosiphon_Factory(heaterProvider);
  }

  /** Proxies {@link Thermosiphon#Thermosiphon(Heater)}. */
  public static Thermosiphon newThermosiphon(Object heater) {
    return new Thermosiphon((Heater) heater);
  }
}

其他的工廠類都是一樣的,都是創建對象和提供對應對象作用.很簡單的類

既然對象工廠有,交互環境也有了,類注入器呢,如何注入呢.但是上面的代碼只知道App 這個類需要注入依賴...,所以只是給

出了MembersInjectors.<App>noOp().injectMembers(coffeeApp),空實現.那麼現在注入代碼如下;

public class App extends Application {
	@Inject
	CoffeeMaker coffeeMaker;
	@Inject
	Heater heater;			//被@inject修飾的對象需要注入依賴						
	@Inject
	Teacher teacher;
	@Inject
	Person person;
	private static final String TAG = "App";
	@Override
	public void onCreate() {
		super.onCreate();

		CoffeeApp build = DaggerCoffeeApp.builder().build();//構建component對象
		build.inject(this);	//注入
		CoffeeMaker coffeeMaker1=coffeeMaker;
		Heater heater1=heater;
		CoffeeApp build3 = DaggerCoffeeApp.builder().build();
		build3.inject(this); //注入
		CoffeeMaker coffeeMaker2=coffeeMaker;
		Heater heater2=heater;
		Log.e(TAG, "onCreate: "+(coffeeMaker2==coffeeMaker1 ));
		Log.e(TAG, "onCreate: "+(heater2==heater1 )); //這個是被@Singleton修飾的,但是結果是false.所謂的單例是

指在這個component實例中只會調用new 對象()方法一次,在這個component實例中我是單例的.但是上面我創建兩個component.所以不等


	}

	public CoffeeMaker getCoffeeMaker(){
		return coffeeMaker;
	}
}
然後重新編譯:

App這個類的注入器已經生成了,代碼如下:

生成代碼如下:

public final class App_MembersInjector implements MembersInjector<App> {
  private final Provider<CoffeeMaker> coffeeMakerProvider;

  private final Provider<Heater> heaterProvider;

  private final Provider<Teacher> teacherProvider;	//持有需要注入依賴對象的工廠

  private final Provider<Person> personProvider;
	//類初始化傳遞工廠
  public App_MembersInjector(
      Provider<CoffeeMaker> coffeeMakerProvider,
      Provider<Heater> heaterProvider,
      Provider<Teacher> teacherProvider,
      Provider<Person> personProvider) {
    assert coffeeMakerProvider != null;
    this.coffeeMakerProvider = coffeeMakerProvider;
    assert heaterProvider != null;
    this.heaterProvider = heaterProvider;
    assert teacherProvider != null;
    this.teacherProvider = teacherProvider;
    assert personProvider != null;
    this.personProvider = personProvider;
  }

  public static MembersInjector<App> create(
      Provider<CoffeeMaker> coffeeMakerProvider,
      Provider<Heater> heaterProvider,
      Provider<Teacher> teacherProvider,
      Provider<Person> personProvider) {
    return new App_MembersInjector(
        coffeeMakerProvider, heaterProvider, teacherProvider, personProvider);
  }

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

	//重點在這裏....通過..App的實例訪問屬性,並通過工廠.get(),方法對屬性賦值
    instance.coffeeMaker = coffeeMakerProvider.get();
    instance.heater = heaterProvider.get();
    instance.teacher = teacherProvider.get();
    instance.person = personProvider.get();
  }
	//以下的方法可以直接訪問,但是如果直接訪問我要你這個dagger框架何用,又如何優雅的解決注入問題呢
  public static void injectCoffeeMaker(App instance, Provider<CoffeeMaker> coffeeMakerProvider) {
    instance.coffeeMaker = coffeeMakerProvider.get();
  }

  public static void injectHeater(App instance, Provider<Heater> heaterProvider) {
    instance.heater = heaterProvider.get();
  }

  public static void injectTeacher(App instance, Provider<Teacher> teacherProvider) {
    instance.teacher = teacherProvider.get();
  }

  public static void injectPerson(App instance, Provider<Person> personProvider) {
    instance.person = personProvider.get();
  }
}

上面的代碼已經得知注入是在injectMembers()方法中的,那它是在什麼地方調用的呢.別忘了外觀類.發生改變如下:
public final class DaggerCoffeeApp implements CoffeeApp {
  private Provider<Heater> provideHeaterProvider;

  private Provider<Thermosiphon> thermosiphonProvider;

  private Provider<Pump> providePumpProvider;

  private Provider<CoffeeMaker> provideMakerProvider;

  private MembersInjector<App> appMembersInjector; //增加類注入器

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

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

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

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

    this.provideHeaterProvider =
        DoubleCheck.provider(
            DripCoffeeModule_ProvideHeaterFactory.create(builder.dripCoffeeModule));

    this.thermosiphonProvider = Thermosiphon_Factory.create(provideHeaterProvider);

    this.providePumpProvider = (Provider) thermosiphonProvider;

    this.provideMakerProvider =
        DripCoffeeModule_ProvideMakerFactory.create(
            builder.dripCoffeeModule, provideHeaterProvider, providePumpProvider);

    this.appMembersInjector =
        App_MembersInjector.create(			// 增加了類注入器的初始化
            provideMakerProvider,
            provideHeaterProvider,
            Teacher_Factory.create(),
            Person_Factory.create());
  }

  @Override
  public void inject(App coffeeApp) {
    appMembersInjector.injectMembers(coffeeApp);  //當調用這個方法時才真正的注入,前期的工作要做好.不然報錯. 實現就是

//上面的啦.
  }

  @Override
  public CoffeeMaker maker() {
    return provideMakerProvider.get();
  }

  public static final class Builder {
    private DripCoffeeModule dripCoffeeModule;

    private Builder() {}

    public CoffeeApp build() {
      if (dripCoffeeModule == null) {
        this.dripCoffeeModule = new DripCoffeeModule();
      }
      return new DaggerCoffeeApp(this);
    }

    public Builder dripCoffeeModule(DripCoffeeModule dripCoffeeModule) {
      this.dripCoffeeModule = Preconditions.checkNotNull(dripCoffeeModule);
      return this;
    }
  }

然後在客戶端調用:
CoffeeApp build = DaggerCoffeeApp.builder().build();
		build.inject(this);	

的確是優雅.簡單.但是中間生成了幾個類:component接口和實現,module ,factory,注入器爲創建對象總共生成了五個類,如果只有

@inject構造注入至少4個類,而創建對象我只需要new 對象()就ok了...需要那麼麻煩嗎,真是令人深思的問題.

ps:以上是對dagger源碼簡單解析...不對地方多指教.類注入器是自己起的,你們隨便叫.......真的跟spring相差甚遠.只想說一句寫註解解析類的纔是大神.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章