前言
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
对于上面的providerMsg2
和providerMsg
会生成两个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
多重绑定
基础使用可看上文
@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"
首先瞅瞅这种复杂Map
的module
的函数
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
会得到所有父component
的module
信息,而父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)
}
}
编译后相关生成类如下:
因为MainActivityComponent
是Subcomponent
所以会生成类在父组件(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()
);
}
}
DispatchingAndroidInjector
是gradle-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
,value
为AndroidInjector.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
}