dagger2的生成源码简单分析

本文详细解析了 Dagger2 的注入机制,包括组件、模块、工厂类及成员注入器的生成过程。通过实例展示了依赖注入的具体实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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相差甚远.只想说一句写注解解析类的才是大神.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值