Dagger2 生成类初探

前言

Dagger2是一个IOC容器,相比起后端的spring来说,Dagger2是编译时完成注入,而spring是运行时.

关于Dagger2的基础知识请参阅官网:
dagger2入门指导

本文意在分析编译后的代码如何注入

基础源码分析

我们首先了解几个契约接口

//Provider.java
package javax.inject;
public interface Provider<T> {

    T get();
}

//Factory.java
package dagger.internal;
public interface Factory<T> extends Provider<T> {
}

每个被@Inject修饰的构造函数都会生成一个工厂类.名字规范为xxx_Factory

open class SuperTest
class CoffeeFilter @Inject constructor()
@Singleton
class Test @Inject constructor() : SuperTest() {}

我们首先查看生成的`Test_Factory.java

//Test_Factory.java
public final class Test_Factory implements Factory<Test> {
  //构建每次调用get都会生成一个新的实例
  @Override
  public Test get() {
    return newInstance();
  }
  //调用一个create生成一个线程安全的懒加载单实例	
  public static Test_Factory create() {
    return InstanceHolder.INSTANCE;
  }

  public static Test newInstance() {
    return new Test();
  }

  private static final class InstanceHolder {
    private static final Test_Factory INSTANCE = new Test_Factory();
  }
}

另一个CoffeeFilter类也是同理

//CoffeeFilter_Factory.java
public final class CoffeeFilter_Factory implements Factory<CoffeeFilter> {
  @Override
  public CoffeeFilter get() {
    return newInstance();
  }

  public static CoffeeFilter_Factory create() {
    return InstanceHolder.INSTANCE;
  }

  public static CoffeeFilter newInstance() {
    return new CoffeeFilter();
  }

  private static final class InstanceHolder {
    private static final CoffeeFilter_Factory INSTANCE = new CoffeeFilter_Factory();
  }
}

我们再来看一个复杂的例子

class Person @Inject constructor() {
    @field:[Inject]
    lateinit var coff: Provider<CoffeeFilter>

    @field:[Inject Named("stringInject")]
    lateinit var fieldString: String

    @field:[Inject Named("stringInject2")]
    lateinit var fieldString2: String

    @field:[Inject Named("testInject2")]
    lateinit var fieldTest2: Test
}

Person自己构造函数被注入,其属性也需要被其他成员注入.
在这种情况下,由于自己构造函数被注入所以会生成Person_Factory,而由于成员也需要注入所以dagger2还会生成一个Person_MembersInjector用于成员属性的赋值.

public final class Person_Factory implements Factory<Person> {
  private final Provider<CoffeeFilter> coffProvider;
  private final Provider<String> fieldStringProvider;
  private final Provider<String> fieldString2Provider;
  private final Provider<Test> fieldTest2Provider;
  //所有Person所需要的注入字段都被放入,工厂类的构造函数中
  public Person_Factory(Provider<CoffeeFilter> coffProvider, Provider<String> fieldStringProvider,
      Provider<String> fieldString2Provider, Provider<Test> fieldTest2Provider) {
    this.coffProvider = coffProvider;
    this.fieldStringProvider = fieldStringProvider;
    this.fieldString2Provider = fieldString2Provider;
    this.fieldTest2Provider = fieldTest2Provider;
  }
  //构造一个多实例,然后调用`Person_MembersInjector`完成属性的注入
  @Override
  public Person get() {
    Person instance = newInstance();
    Person_MembersInjector.injectCoff(instance, coffProvider);
    Person_MembersInjector.injectFieldString(instance, fieldStringProvider.get());
    Person_MembersInjector.injectFieldString2(instance, fieldString2Provider.get());
    Person_MembersInjector.injectFieldTest2(instance, fieldTest2Provider.get());
    return instance;
  }
  //提供的一个便捷函数
  public static Person_Factory create(Provider<CoffeeFilter> coffProvider,
      Provider<String> fieldStringProvider, Provider<String> fieldString2Provider,
      Provider<Test> fieldTest2Provider) {
    return new Person_Factory(coffProvider, fieldStringProvider, fieldString2Provider, fieldTest2Provider);
  }

  public static Person newInstance() {
    return new Person();
  }
}

dagger2对于属性的注入,单独提供一个类帮助我们进行注入.其规范名为xxxx_MembersInjector.

Person_MembersInjector

public final class Person_MembersInjector implements MembersInjector<Person> {

  //这个几个属性都是Person需要注入的属性	
  private final Provider<CoffeeFilter> coffProvider;
  private final Provider<String> fieldStringProvider;
  private final Provider<String> fieldString2Provider;
  private final Provider<Test> fieldTest2Provider;
 //构造函数传入所需的注入属性实例
  public Person_MembersInjector(Provider<CoffeeFilter> coffProvider,
      Provider<String> fieldStringProvider, Provider<String> fieldString2Provider,
      Provider<Test> fieldTest2Provider) {
    this.coffProvider = coffProvider;
    this.fieldStringProvider = fieldStringProvider;
    this.fieldString2Provider = fieldString2Provider;
    this.fieldTest2Provider = fieldTest2Provider;
  }
  //一个快捷构造Person_MembersInjector方法
  public static MembersInjector<Person> create(Provider<CoffeeFilter> coffProvider,
      Provider<String> fieldStringProvider, Provider<String> fieldString2Provider,
      Provider<Test> fieldTest2Provider) {
    return new Person_MembersInjector(coffProvider, fieldStringProvider, fieldString2Provider, fieldTest2Provider);
  }
  //将对象注入到指定的Person实例中
  @Override
  public void injectMembers(Person instance) {
    injectCoff(instance, coffProvider);
    injectFieldString(instance, fieldStringProvider.get());
    injectFieldString2(instance, fieldString2Provider.get());
    injectFieldTest2(instance, fieldTest2Provider.get());
  }
  //属性单独注入
  @InjectedFieldSignature("Person.coff")
  public static void injectCoff(Person instance, Provider<CoffeeFilter> coff) {
    instance.coff = coff;
  }
  //属性单独注入
  @InjectedFieldSignature("Person.fieldString")
  @Named("stringInject")
  public static void injectFieldString(Person instance, String fieldString) {
    instance.fieldString = fieldString;
  }
   //属性单独注入
  @InjectedFieldSignature("Person.fieldString2")
  @Named("stringInject2")
  public static void injectFieldString2(Person instance, String fieldString2) {
    instance.fieldString2 = fieldString2;
  }
  //属性单独注入
  @InjectedFieldSignature("Person.fieldTest2")
  @Named("testInject2")
  public static void injectFieldTest2(Person instance, Test fieldTest2) {
    instance.fieldTest2 = fieldTest2;
  }
}

我们看下Module相关生成类


class CoffeeFilter @Inject constructor()
@Singleton
class Test @Inject constructor() : SuperTest() {}

@Module
abstract class MyModule {

    //包含抽象函数的module,对于非抽象方法必须是静态的
    companion object {
        @Provides
        @Named("stringInject")
        fun providerMsg(@Named("msgflag") named: String): String {
            //简单拼接后缀
            return String.format(named + "------");
        }

        @Provides
        @Named("stringInject2")
        @Singleton
        fun providerMsg2(): String {
            return String.format("你好");
        }
    }
    @Binds
    abstract fun bindTest(t: Test): SuperTest;
}

对于每个Module@Provides都会生成一个工厂类.其规范名为外部类_外部类2_函数名Factory
对于上面的providerMsg2providerMsg会生成两个MyModule_Companion_ProviderMsg2Factory,MyModule_Companion_ProviderMsgFactory,你可能会疑惑生成的类名包含一个Companion在中间,是因为kotlin静态方法和静态属性的一些特性,kotlin会生成一个Companion去存储静态相关方法属性.

  • @Binds 为什么没有生成对应工程类?,因为传入Test已经在其构造函数的注入了,所以会生成一个Test_Factory,这里@Binds没必要生成.
//MyModule_Companion_ProviderMsgFactory.java
public final class MyModule_Companion_ProviderMsgFactory implements Factory<String> {
  private final Provider<String> namedProvider;

 //传入调用providerMsg所需要的字符串
  public MyModule_Companion_ProviderMsgFactory(Provider<String> namedProvider) {
    this.namedProvider = namedProvider;
  }
  //用构造函数得到的传入字符串,调用函数并返回结果
  @Override
  public String get() {
    return providerMsg(namedProvider.get());
  }
 //便捷函数
  public static MyModule_Companion_ProviderMsgFactory create(Provider<String> namedProvider) {
    return new MyModule_Companion_ProviderMsgFactory(namedProvider);
  }
  //用传入的字符串调用原始的函数
  public static String providerMsg(String named) {
    return Preconditions.checkNotNullFromProvides(MyModule.Companion.providerMsg(named));
  }
}

//MyModule_Companion_ProviderMsg2Factory.java
//同上不再将
public final class MyModule_Companion_ProviderMsg2Factory implements Factory<String> {
  @Override
  public String get() {
    return providerMsg2();
  }

  public static MyModule_Companion_ProviderMsg2Factory create() {
    return InstanceHolder.INSTANCE;
  }

  public static String providerMsg2() {
    return Preconditions.checkNotNullFromProvides(MyModule.Companion.providerMsg2());
  }

  private static final class InstanceHolder {
    private static final MyModule_Companion_ProviderMsg2Factory INSTANCE = new MyModule_Companion_ProviderMsg2Factory();
  }
}

我们最后结合讲一下Component.结合上面的所有代码:


open class SuperTest

class CoffeeFilter @Inject constructor()
@Singleton
class Test @Inject constructor() : SuperTest() {}

@Module
abstract class MyModule {

    //包含抽象函数的module,对于非抽象方法必须是静态的
    companion object {
        @Provides
        @Named("stringInject")
        fun providerMsg(@Named("msgflag") named: String): String {
            //简单拼接后缀
            return String.format(named + "------");
        }

        @Provides
        @Named("stringInject2")
        @Singleton
        fun providerMsg2(): String {
            return String.format("你好");
        }
    }
    @Binds
    abstract fun bindTest(t: Test): SuperTest;
}


@Component(modules = [MyModule::class])
@Singleton
interface MyComponent {
    fun make(): Person
    fun make2(): SuperTest
    fun make3(): CoffeeFilter
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun buildName(@Named("msgflag") userName: String): Builder
        @BindsInstance
        fun buildTest(@Named("testInject2") test: Test): Builder
        fun build(): MyComponent
    }

}


class Person @Inject constructor() {
    @field:[Inject]
    lateinit var coff: Provider<CoffeeFilter>
    @field:[Inject Named("stringInject")]
    lateinit var fieldString: String
    @field:[Inject Named("stringInject2")]
    lateinit var fieldString2: String
    @field:[Inject Named("testInject2")]
    lateinit var fieldTest2: Test
    @field:[Inject ]
    lateinit var fieldTest3: SuperTest
}

我们把重心放到component

@Component(modules = [MyModule::class])
@Singleton
interface MyComponent {
    fun make(): Person
    fun make2(): SuperTest
    fun make3(): CoffeeFilter
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun buildName(@Named("msgflag") userName: String): Builder
        @BindsInstance
        fun buildTest(@Named("testInject2") test: Test): Builder
        fun build(): MyComponent
    }
}

@Component.Builder会生成一个建造者模式的相关类,而@BindsInstance会生成建造模式的相关函数.

  • 建造者模式:屏蔽所需类的构造细节,只需通过构造类分步的函数传入参数,最后通过build返回所需类

于是我们会得到以下的构造类

private static final class Builder implements MyComponent.Builder {
    private String buildName;

    private Test buildTest;

    @Override
    public Builder buildName(String userName) {
      this.buildName = Preconditions.checkNotNull(userName);
      return this;
    }

    @Override
    public Builder buildTest(Test test) {
      this.buildTest = Preconditions.checkNotNull(test);
      return this;
    }

    @Override
    public MyComponent build() {
      //非空检查	
      Preconditions.checkBuilderRequirement(buildName, String.class);
      //非空检查
      Preconditions.checkBuilderRequirement(buildTest, Test.class);
      return new DaggerMyComponent(buildName, buildTest);
    }
  }
//DaggerMyComponent.java
public final class DaggerMyComponent implements MyComponent {
  //构造器传入的属性
  private final String buildName;
  //构造器传入的属性
  private final Test buildTest;
  //这个要注入到person所需要的对象
  private Provider<String> providerMsg2Provider;
  //这个是make2所需的对象
  private Provider<Test> testProvider;
  
  //构造类传入的参数	
  private DaggerMyComponent(String buildNameParam, Test buildTestParam) {
    this.buildName = buildNameParam;
    this.buildTest = buildTestParam;
    initialize(buildNameParam, buildTestParam);
  }
  //所有的单例都会在initialize中初始化
private void initialize(final String buildNameParam, final Test buildTestParam) {
    this.providerMsg2Provider = DoubleCheck.provider(MyModule_Companion_ProviderMsg2Factory.create());
    this.testProvider = DoubleCheck.provider(Test_Factory.create());
  }

 //向外暴露的函数
  @Override
  public Person make() {
    return injectPerson(Person_Factory.newInstance());
  }
 //向外暴露的函数
  @Override
  public SuperTest make2() {
    return testProvider.get();
  }
 //向外暴露的函数
  @Override
  public CoffeeFilter make3() {
    return new CoffeeFilter();
  }
  //我们先忽视下面的代码	
  private String namedString() {
    return MyModule_Companion_ProviderMsgFactory.providerMsg(buildName);
  }
  //我们先忽视下面的代码
  private Person injectPerson(Person instance) {
    Person_MembersInjector.injectCoff(instance, CoffeeFilter_Factory.create());
    Person_MembersInjector.injectFieldString(instance, namedString());
    Person_MembersInjector.injectFieldString2(instance, providerMsg2Provider.get());
    Person_MembersInjector.injectFieldTest2(instance, buildTest);
    Person_MembersInjector.injectFieldTest3(instance, testProvider.get());
    return instance;
  }


}

  • make2

我们依次分析分析所有的暴露函数

//向外暴露的函数
  @Override
  public SuperTest make2() {
    return testProvider.get();
  }
private void initialize(final String buildNameParam, final Test buildTestParam) {
	//DoubleCheck.provider用于封装成provider对象
	//而其Test_Factory.create()返回一个单例对象
    this.testProvider = DoubleCheck.provider(Test_Factory.create());
  }
//我们回过头再看看Test_Factory
public final class Test_Factory implements Factory<Test> {
  @Override
  public Test get() {
    return newInstance();
  }

  public static Test_Factory create() {
    return InstanceHolder.INSTANCE;
  }

  public static Test newInstance() {
    return new Test();
  }

  private static final class InstanceHolder {
    private static final Test_Factory INSTANCE = new Test_Factory();
  }
}

为什么他会生成一个单例呢?因为我们用@Singleton注释了Test

@Singleton
class Test @Inject constructor() : SuperTest() {}

当然你的单例注释也可以放在@Binds@Provides上,如下代码

 	@Binds
    @Singleton
    abstract fun bindTest(t: Test): SuperTest;
  • make3
 //向外暴露的函数
  @Override
  public CoffeeFilter make3() {
    return new CoffeeFilter();
  }

由于CoffeeFilter并没有使用Singleton注释,所以直接new一个新实例即可.可能你会想既然dagger2不是为这个类生成了CoffeeFilter_Factory,为什么不用它来生成对象呢?因为通过CoffeeFilter_Factory还需要而外的函数调用,性能不如直接new高.

  • make
//向外暴露的函数
  @Override
  public Person make() {
    return injectPerson(Person_Factory.newInstance());
  }
  

这个应该是最难的注入分析

public final class DaggerMyComponent implements MyComponent {
  private final String buildName;
  private final Test buildTest;

  private Provider<String> providerMsg2Provider;

  private DaggerMyComponent(String buildNameParam, Test buildTestParam) {
    this.buildName = buildNameParam;
    this.buildTest = buildTestParam;
    //所有的单例都会在initialize中初始化
    initialize(buildNameParam, buildTestParam);
  }

 
  private String namedString() {
    return MyModule_Companion_ProviderMsgFactory.providerMsg(buildName);
  }
  //所有的单例都会在initialize中初始化	
  private void initialize(final String buildNameParam, final Test buildTestParam) {
    this.providerMsg2Provider = DoubleCheck.provider(MyModule_Companion_ProviderMsg2Factory.create());
    this.testProvider = DoubleCheck.provider(Test_Factory.create());

  }

  @Override
  public Person make() {
    //Person_Factory.newInstance() 构造一个多实例的Person返回
    //injectPerson用于注入
    return injectPerson(Person_Factory.newInstance());
  }

  private Person injectPerson(Person instance) {
    //注入CoffeeFilter,这里是一个多实例哦
    Person_MembersInjector.injectCoff(instance, CoffeeFilter_Factory.create());
    //stringInject是一个多实例哦,所以每次注入时都调用model的函数获取一个新的字符串
    Person_MembersInjector.injectFieldString(instance, namedString());
    //providerMsg2Provider在initialize获得,也就是通过module中获取对应的函数
    //注意fieldString2是一个单例哦
    //providerMsg2函数被@Singleton修饰
    Person_MembersInjector.injectFieldString2(instance, providerMsg2Provider.get());
    //buildTest在建造者模式传入
    Person_MembersInjector.injectFieldTest2(instance, buildTest);
    //testProvider 在initialize初始化,注意Test被@Singleton修饰
    Person_MembersInjector.injectFieldTest3(instance, testProvider.get());

    return instance;
  }

 
}

通过上面我们大致明白了单例会在initialize中初始化后进行复用,而非单例每次都会调用对应的方法获取.
所以单例仅限同一个Component实例中,而非多个Component实例.
举个例子:

fun main() {

    val create = DaggerMyComponent
        .builder()
        .buildName("helo")
        .buildTest(Test())
        .build()
    val create2 = DaggerMyComponent
        .builder()
        .buildName("helo")
        .buildTest(Test())
        .build()

    println(create.make().fieldTest3)
    println(create.make().fieldTest3)
    println("-------")
    println(create2.make().fieldTest3)
    println(create2.make().fieldTest3)
}

输出

Test@3f99bd52
Test@3f99bd52
-------
Test@4f023edb
Test@4f023edb

多重绑定

Multibindings官方使用说明

基础使用可看上文


@Module
abstract class MyModule {

    //包含抽象函数的module,对于非抽象方法必须是静态的
    companion object {
        @Provides
        @IntoSet
        fun provideOneString(): String {
            return "ABC"
        }

        @Provides
        @IntoSet
        fun provideTwoString(): String {
            return "DEF"
        }

        @Provides
        @ElementsIntoSet
        fun provideThreeString(): Set<String> {
            return setOf("HIJ", "KLM")
        }
    }

}


@Component(modules = [MyModule::class])
@Singleton
interface MyComponent {
    fun make(): Person
}


class Person @Inject constructor() {
    @field:[Inject ]
    lateinit var list: Set<String>

}

fun main() {
    val create = DaggerMyComponent.create()
    println(create.make().list)
    println(create.make().list)


}

输出:

[ABC, DEF, HIJ, KLM]
[ABC, DEF, HIJ, KLM]

关于Module的生成类比较简单,我们这里就跳过.

我们细看下如何实现注入的

public final class DaggerMyComponent implements MyComponent {
    private DaggerMyComponent() {

    }

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

    public static MyComponent create() {
        return new Builder().build();
    }

    private Set<String> setOfString() {
    //构建一个集合类,将module所有符合的集合类进行装配
        return SetBuilder.<String>newSetBuilder(3)
         		//添加单个元素
                .add(MyModule_Companion_ProvideOneStringFactory.provideOneString()) 
                //添加单个元素
                .add(MyModule_Companion_ProvideTwoStringFactory.provideTwoString())                 
				//添加一个集合
				.addAll(MyModule_Companion_ProvideThreeStringFactory.provideThreeString()) 
                .build();
    }

    @Override
    public Person make() {
        return injectPerson(Person_Factory.newInstance());
    }

    private Person injectPerson(Person instance) {
    	//将集合注入
        Person_MembersInjector.injectList(instance, setOfString());
        return instance;
    }

}

比较简单,就是将所有module元素重新组合在一起,在注入.

复杂的map相关


@MapKey(unwrapValue = false)
@interface MyKey {
    String name();
    Class<?> implementingClass();
    int[] thresholds();
}

@Module
class MyModule {

    @Provides
    @IntoMap
    @MyKey(name = "abc", implementingClass = MyMain.class, thresholds = {1, 5, 10})
    static String provideAbc1510Value() {
        return "foo";
    }

    @Provides
    @IntoMap
    @MyKey(name = "abc2", implementingClass = MyMain.class, thresholds = {1, 5, 10})
    static String provideAbc1510Value2() {
        return "foo";
    }


}

@Component(modules = MyModule.class)
interface MyComponent {
    Map<MyKey, String> myKeyStringMap();
}


public class MyMain {

    static MyKey createMyKey(String name, Class<?> implementingClass, int[] thresholds) {
    	//AutoAnnotation_MyKeyCreator_createMyKey是autovalue实现动态生成类,用于生成一个集成MyKey的类
        return new AutoAnnotation_MyKeyCreator_createMyKey(name, implementingClass, thresholds);
    }

    public static void main(String[] args) {
        MyComponent myComponent = DaggerMyComponent.create();
        String abc = myComponent.myKeyStringMap()
                .get(createMyKey("abc", MyMain.class, new int[]{1, 5, 10}));
        System.out.println(abc);
    }
}

输出:

foo

上面的代码请添加autovalue相关依赖:

 compileOnly "com.google.auto.value:auto-value-annotations:1.8.1"
    kapt "com.google.auto.value:auto-value:1.8.1"

首先瞅瞅这种复杂Mapmodule的函数

public final class MyModule_ProvideAbc1510Value2Factory implements Factory<String> {
  @Override
  public String get() {
    return provideAbc1510Value2();
  }

  public static MyModule_ProvideAbc1510Value2Factory create() {
    return InstanceHolder.INSTANCE;
  }

  public static String provideAbc1510Value2() {
    return Preconditions.checkNotNullFromProvides(MyModule.provideAbc1510Value2());
  }

  private static final class InstanceHolder {
    private static final MyModule_ProvideAbc1510Value2Factory INSTANCE = new MyModule_ProvideAbc1510Value2Factory();
  }
}

autovalue会帮我们生一个MyKey的实现

@Generated("com.google.auto.value.processor.AutoAnnotationProcessor")
final class AutoAnnotation_MyKeyCreator_createMyKey implements MyKey, Serializable {
  
  private static final long serialVersionUID = 559734305552072226L;
  private final String name;
  private final Class<?> implementingClass;
  private final int[] thresholds;

  AutoAnnotation_MyKeyCreator_createMyKey(
      String name,
      Class<?> implementingClass,
      int[] thresholds) {
    if (name == null) {
      throw new NullPointerException("Null name");
    }
    this.name = name;
    if (implementingClass == null) {
      throw new NullPointerException("Null implementingClass");
    }
    this.implementingClass = implementingClass;
    if (thresholds == null) {
      throw new NullPointerException("Null thresholds");
    }
    this.thresholds = thresholds.clone();
  }
  
 //注意equals的实现是比较其元素是否相等,而不是直接==
  @Override
  public boolean equals(Object o) {
    if (o == this) {
      return true;
    }
    if (o instanceof MyKey) {
      MyKey that = (MyKey) o;
      return name.equals(that.name())
          && implementingClass.equals(that.implementingClass())
          && Arrays.equals(thresholds,
          (that instanceof AutoAnnotation_MyKeyCreator_createMyKey)
          ? ((AutoAnnotation_MyKeyCreator_createMyKey) that).thresholds
          : that.thresholds());
    }
    return false;
  }	
}

最后看看Component的实现

final class DaggerMyComponent implements MyComponent {
  private DaggerMyComponent() {}

  @Override
  public Map<MyKey, String> myKeyStringMap() {
     	//成对出现 第一个作为key,第二个作为value
        return ImmutableMap.<MyKey, String>of(
                //第一个作为key
                MyKeyCreator.createMyKey("abc", MyMain.class, new int[]{1, 5, 10}),
                //第二个作为value
                MyModule_ProvideAbc1510ValueFactory.provideAbc1510Value(),
                //第一个作为key
                MyKeyCreator.createMyKey("abc2", MyMain.class, new int[]{1, 5, 10}),
                //第二个作为value
                MyModule_ProvideAbc1510Value2Factory.provideAbc1510Value2());
  }

}

dagger利用autovalue生成复杂的key,在用其创建map.

Subcomponents

Dagger 2 完全解析(三),Component与SubComponent

  • 首先看一个案例:


class Parent {
    @field:[Inject]
    lateinit var car: Car

    @field:[Inject]
    lateinit var msSet: Set<String>


}

class Child {
    @Inject
    lateinit var car: Car

    @Inject
    lateinit var bike: Bike


    @field:[Inject]
    lateinit var msSet: Set<String>

}

class Car constructor()
class Bike constructor()


@Component(modules = [CarModule::class])
interface ParentComponent {
    fun inject(parent: Parent)
    fun childComponent(): ChildComponent.Builder

}

@Subcomponent(modules = [BikeModule::class])
interface ChildComponent {
    fun inject(child: Child)

    // SubComponent 必须显式地声明 Subcomponent.Builder,parentComponent 需要用 Builder 来创建 ChildComponent
    @Subcomponent.Builder
    interface Builder {
        fun build(): ChildComponent
    }
}

@Module(subcomponents = [ChildComponent::class])
class CarModule {
    @Provides
    fun provideCar() = Car()


    @Provides
    @IntoSet
    fun provideOne(): String = "2"


    @Provides
    @IntoSet
    fun provideTwo(): String = "3"


}

@Module
class BikeModule {
    @Provides
    fun provideBike() = Bike()

    @Provides
    @IntoSet
    fun provideThree(): String = "4"


    @Provides
    @IntoSet
    fun provideFour(): String = "5"
}

fun main() {
    val parentComponent = DaggerParentComponent.builder().build()
    val child = Child()
    parentComponent.childComponent().build().inject(child)
    val parent = Parent()
    parentComponent.inject(parent)
    
    println(parent.msSet)
    println(child.msSet)
}

输出:

[2, 3]
[2, 3, 4, 5]

上面代码在编译后会将子component生成类,放入父component作为内部类.

//DaggerParentComponent.java
public final class DaggerParentComponent implements ParentComponent {
  
  private final class ChildComponentBuilder implements ChildComponent.Builder {
    @Override
    public ChildComponent build() {
      return new ChildComponentImpl(new BikeModule());
    }
  }

  private final class ChildComponentImpl implements ChildComponent {
   
  }

    
}

我看下我们父子注入set集合的区别



  private final class ChildComponentImpl implements ChildComponent {
    private final BikeModule bikeModule;

    private ChildComponentImpl(BikeModule bikeModuleParam) {
      this.bikeModule = bikeModuleParam;
    }

    private Set<String> setOfString() {
      return ImmutableSet.<String>of(
              //父亲的set
              CarModule_ProvideOneFactory.provideOne(DaggerParentComponent.this.carModule),
              //父亲的set
              CarModule_ProvideTwoFactory.provideTwo(DaggerParentComponent.this.carModule),
              //子组件的set
              BikeModule_ProvideThreeFactory.provideThree(bikeModule),
              //子组件的set
              BikeModule_ProvideFourFactory.provideFour(bikeModule)
      );
    }

    @Override
    public void inject(Child child) {
      injectChild(child);
    }

    @CanIgnoreReturnValue
    private Child injectChild(Child instance) {
      //...略
      //注入父组件的set和子组件的set
      Child_MembersInjector.injectMsSet(instance, setOfString());
      return instance;
    }

  }


可以看到子组件会拉取所有父组件的信息.

最后看看父component

public final class DaggerParentComponent implements ParentComponent {
	 private Set<String> setOfString() {
        return ImmutableSet.<String>of(
                //仅父module的set
                CarModule_ProvideOneFactory.provideOne(carModule),
                //仅父module的set
                CarModule_ProvideTwoFactory.provideTwo(carModule));
    }
 private Parent injectParent(Parent instance) {
  	//仅注入父的module所提供的set
    Parent_MembersInjector.injectMsSet(instance, setOfString());
    return instance;
  }
}

综上:
子component会得到所有父componentmodule信息,而父component仅能获取自身的module.

Dependencies

基础语法参考链接:Dagger 2 完全解析(三),Component与SubComponent

  • 案例:

@Module
class AModule {
    @Provides
    @Named("Name")
    fun provideName() = "XiaoZhang"
}

@Module

class BModule {
    @Provides
    @Named("Age")
    fun provideAge() = 13
}

@Component(modules = [AModule::class])
interface AComponent {
    @Named("Name")
    fun obtainName(): String
}

@Component(dependencies = [AComponent::class], modules = [BModule::class])
interface BComponent {
    @Named("Age")
    fun obtainAge(): Int

    @Named("Name")
    fun obtainName(): String
}

fun main() {
    val bComponent = DaggerBComponent.builder()
        .aComponent(DaggerAComponent.create())
        .build()

    println(bComponent.obtainName())
    println(bComponent.obtainAge())
}

编译后依赖其他组件的component生成类会包含其引用

public final class DaggerBComponent implements BComponent {
  private final BModule bModule;

  private final AComponent aComponent;

  private DaggerBComponent(BModule bModuleParam, AComponent aComponentParam) {
    this.bModule = bModuleParam;
    this.aComponent = aComponentParam;
  }

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

  @Override
  public int obtainAge() {
    return bModule.provideAge();
  }
 //获取依赖组件的信息时,直接调用依赖组件的component
  @Override
  public String obtainName() {
    return Preconditions.checkNotNullFromComponent(aComponent.obtainName());
  }

  public static final class Builder {
    private BModule bModule;

    private AComponent aComponent;

    private Builder() {
    }

	//建造者模式强制要求传入依赖的组件	
    public Builder aComponent(AComponent aComponent) {
      this.aComponent = Preconditions.checkNotNull(aComponent);
      return this;
    }
    
    public BComponent build() {
      if (bModule == null) {
        this.bModule = new BModule();
      }
      return new DaggerBComponent(bModule, aComponent);
    }
  }
}

Android 相关

为了方便Android开发者使用dagger2,官方对其基础api做了封装,您可以使用如下依赖

  implementation 'com.google.dagger:dagger-android:2.34.1'
  implementation 'com.google.dagger:dagger:2.34.1'
  kapt 'com.google.dagger:dagger-android-processor:2.34.1'
  kapt 'com.google.dagger:dagger-compiler:2.34.1'

官方基础教程

来一个Demo

//MainActivityComponent.java
@Subcomponent(modules = {MainActivityModule.class})
public interface MainActivityComponent extends AndroidInjector<MainActivity> {
    @Subcomponent.Factory
    interface Factory extends AndroidInjector.Factory<MainActivity> {}
}

@Module
abstract class MainActivityModule {
    @Provides
    @Named("ActivityStr")
    static String provideStr() {
        return "I'm MainActivityModule";
    }
}

上面用于声明哪个Activity将被注入.

Subcomponent会被声明在父组件的module,于是我们把所有actvity的声明放入一个叫ActivitiesModule

//ActivitiesModule.java
@Module(subcomponents = MainActivityComponent.class)
public abstract class ActivitiesModule {

    @Binds
    @IntoMap
    @ClassKey(MainActivity.class)
    abstract AndroidInjector.Factory<?>
    bindYourAndroidInjectorFactory(MainActivityComponent.Factory factory);
}

最后看下父component

//AppComponent.java
@Component(modules = {
        AndroidInjectionModule.class,//google 官方教程说明居然没说这个有点坑
        ActivitiesModule.class,
        AppModule.class})
public interface AppComponent {
    void inject(App app);
}

@Module
abstract class AppModule {

    @Provides
    @Named("AppStr")
    static String provide() {
        return "Appstr";
    }
}

最后看下android组件类

//App.java
public class App extends Application implements HasAndroidInjector {
    @Inject
    DispatchingAndroidInjector<Object> dispatchingAndroidInjector;

    @Inject
    @Named("AppStr")
    String applicationMsg;

    @Override
    public void onCreate() {
        super.onCreate();

        DaggerAppComponent.create().inject(this);

    }

    @Override
    public AndroidInjector<Object> androidInjector() {
        return dispatchingAndroidInjector;
    }
}


//MainActivity.java
class MainActivity : AppCompatActivity() {


    @Inject
    @Named("ActivityStr")
    lateinit var applicationMsg: String


    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }
}

编译后相关生成类如下:
在这里插入图片描述

因为MainActivityComponentSubcomponent所以会生成类在父组件(DaggerAppComponent)中,

public final class DaggerAppComponent implements AppComponent {

 //Subcomponent的工厂类
 private final class MainActivityComponentFactory implements MainActivityComponent.Factory {
    @Override
    public MainActivityComponent create(MainActivity arg0) {
      Preconditions.checkNotNull(arg0);
      return new MainActivityComponentImpl(arg0);
    }
  }
  
  private final class MainActivityComponentImpl implements MainActivityComponent {

    private MainActivityComponentImpl(MainActivity arg0) {}

    @Override
    public void inject(MainActivity arg0) {
      injectMainActivity(arg0);
    }
    
	//字符串注入到MainActivity的相关代码,比较简单
    private MainActivity injectMainActivity(MainActivity instance) {
      MainActivity_MembersInjector.injectApplicationMsg(instance, MainActivityModule_ProvideStrFactory.provideStr());
    
      return instance;
    }

  }

}

上面子类比较简单,比较复杂的是ActivitiesModule,它的实现也位于DaggerAppComponent

//ActivitiesModule.java
@Module(subcomponents = MainActivityComponent.class)
public abstract class ActivitiesModule {

    @Binds
    @IntoMap
    @ClassKey(MainActivity.class)
    abstract AndroidInjector.Factory<?>
    bindYourAndroidInjectorFactory(MainActivityComponent.Factory factory);
}


public final class DaggerAppComponent implements AppComponent {
    private Provider<MainActivityComponent.Factory> mainActivityComponentFactoryProvider;
	  
	  //去掉泛型:Map mapOfClassOfAndProviderOfAndroidInjectorFactoryOf(){...}
	  private Map<Class<?>, Provider<AndroidInjector.Factory<?>>> mapOfClassOfAndProviderOfAndroidInjectorFactoryOf(
    ) {
        //我们把泛型去掉可能看的更清楚:Collections.singletonMap(key1,value1)
        //singletonMap构造一个以MainActivity.class为key,MainActivityComponent.Factory为value的map实例
        return Collections.<Class<?>, Provider<AndroidInjector.Factory<?>>>singletonMap(
                MainActivity.class,
                (Provider) mainActivityComponentFactoryProvider
        );
    }
   //函数返回App类所需的注入对象.DispatchingAndroidInjector
    private DispatchingAndroidInjector<Object> dispatchingAndroidInjectorOfObject() {
        return DispatchingAndroidInjector_Factory.newInstance(
                //这里就是ActivitiesModule收集到的
                mapOfClassOfAndProviderOfAndroidInjectorFactoryOf(),
                //这里会放入一个空集合是因为AppComponent的AndroidInjectionModule内部有一个@Multibinds.而DispatchingAndroidInjector需要两个map于是就从AndroidInjectionModule返回的map中拿
                Collections.<String, Provider<AndroidInjector.Factory<?>>>emptyMap()
        );
    }
}

DispatchingAndroidInjectorgradle-android库中的一个类,声明如下:

public final class DispatchingAndroidInjector<T> implements AndroidInjector<T> {
  //将两个构造函数的map进行合并
  private final Map<String, Provider<AndroidInjector.Factory<?>>> injectorFactories;

  @Inject
  DispatchingAndroidInjector(
      Map<Class<?>, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithClassKeys,
      Map<String, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithStringKeys) {
    //Map<Class<?>, Provider<AndroidInjector.Factory<?>>>会转化为字符串map,class会转为类全限定名
    this.injectorFactories = merge(injectorFactoriesWithClassKeys, injectorFactoriesWithStringKeys);
  }

注意构造函数被@Inject修饰,所以会生成一个对应工厂类DispatchingAndroidInjector_Factory,

public final class DispatchingAndroidInjector_Factory<T> implements Factory<DispatchingAndroidInjector<T>> {

//...略

 
 public static <T> DispatchingAndroidInjector<T> newInstance(
      Map<Class<?>, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithClassKeys,
      Map<String, Provider<AndroidInjector.Factory<?>>> injectorFactoriesWithStringKeys) {
    return new DispatchingAndroidInjector<T>(injectorFactoriesWithClassKeys, injectorFactoriesWithStringKeys);
  }
}

上面我们大致明白了DispatchingAndroidInjector内部有一个map结构,以类的全限定名为key,valueAndroidInjector.Factory.由于AndroidInjector.Factory是一个component,所以他可以执行注入.
在这里插入图片描述
我们最后在回头细看Activity如何注入

class MainActivity : AppCompatActivity() {


    @Inject
    @Named("ActivityStr")
    lateinit var applicationMsg: String


    override fun onCreate(savedInstanceState: Bundle?) {
    	//看这
        AndroidInjection.inject(this);
       

    }
}

//AndroidInjection.java
public static void inject(Activity activity) {
  
    Application application = activity.getApplication();
    //要求application强制实现HasAndroidInjectorj接口,否则出错
    if (!(application instanceof HasAndroidInjector)) {
      throw new RuntimeException(
          String.format(
              "%s does not implement %s",
              application.getClass().getCanonicalName(),
              HasAndroidInjector.class.getCanonicalName()));
    }

    inject(activity, (HasAndroidInjector) application);
  }
  private static void inject(Object target, HasAndroidInjector hasAndroidInjector) {
    //获取内部的DispatchingAndroidInjector对象
    AndroidInjector<Object> androidInjector = hasAndroidInjector.androidInjector();
   	//执行注入
    androidInjector.inject(target);
  }

public final class DispatchingAndroidInjector<T> implements AndroidInjector<T> {
 private final Map<String, Provider<AndroidInjector.Factory<?>>> injectorFactories;

 public void inject(T instance) {
 	//成功注入返回true
    boolean wasInjected = maybeInject(instance);
    if (!wasInjected) {
      throw new IllegalArgumentException(errorMessageSuggestions(instance));
    }
  }
  public boolean maybeInject(T instance) {
   //用类的全限定名获取对应component
    Provider<AndroidInjector.Factory<?>> factoryProvider =
        injectorFactories.get(instance.getClass().getName());
    //如果map没有就返回
    if (factoryProvider == null) {
      return false;
    }

   //获取工程类
    AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
    try {
    //实例化工程类
		//相当于    	AndroidInjector<T> injector = factory.create(instance),
      AndroidInjector<T> injector =
          checkNotNull(
              factory.create(instance),

 "%s.create(I) should not return null.", factory.getClass());

	  //注入
      injector.inject(instance);

      return true;
    } catch (ClassCastException e) {
      throw new InvalidInjectorBindingException(
          String.format(
              "%s does not implement AndroidInjector.Factory<%s>",
              factory.getClass().getCanonicalName(), instance.getClass().getCanonicalName()),
          e);
    }
  }	
}

我们留个神 看看factory.create(instance),

 AndroidInjector<T> injector =
          checkNotNull(
              factory.create(instance),

 "%s.create(I) should not return null.", factory.getClass());
    AndroidInjector<T> create(@BindsInstance T instance);

看到一个@BindsInstance修饰的构造器函数,所以传入的参数可以被注入.而我们传入的对象是Activity,所以以下代码也是正确的

class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var instance: MainActivity
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值