下面主要分析,Dagger 中使用 @Inject 注解一个构造方法来提供依赖的过程。
老王已经拿到驾驶证了,说飙车就能飙车:
通过 @Inject 来标注 Person 中需要使用 Car:
public class Person {
@Inject
Car car;
public void goDongbei(){
car.run();
}
}
老王从老李哪里借了一辆 GTR,两人签了一个借车合约(PersonComponent):
PersonComponent 接口表明需要向 Person 中注入一些依赖:
@Component
public interface PersonComponent {
void inject(Person person);
}
Car的构造函数使用 @Inject 来提供依赖:
public class Car {
private static final String TAG = "Car";
@Inject
Car(){}
public void run(){
Log.d(TAG, "run: 一起去东北");
}
}
三者关系如下:
Car 老王去东北的依赖工具------为依赖的提供者,此处通过 @Inject 标注其构造方法来指明
Person 一个说飙车就飙车的老王-------为依赖的使用者,此处通过 @Inject 标注其要使用的依赖类
PersonComponent 借车合约----------将 Car 提供给 Person 使用,其中 void inject(Person person) 表明需要向 Person 中注入一些依赖。
此时,build一把工程,然后添加如下代码:
Person person = new Person();
DaggerPersonComponent.builder().build().inject(person);
person.goShopping();
最后run一把工程,输出如下:
2019-04-17 14:38:13.046 4772-4772/com.example.demo_dagger2 D/Car: run: ~~~~~~
run: 一起去东北
那么问题来了,Dagger 怎么凭借 DaggerPersonComponent.builder().build().inject(person) 一个链式调用就把 Car 对象注入到 Person 的呢?
先看看 DaggerPersonComponent 到底是什么?
DaggerPersonComponent 为工程 build 后 Dagger 利用注解自动生成的代码
// Generated by dagger.internal.codegen.ComponentProcessor (https://google.github.io/dagger).
public final class DaggerPersonComponent implements PersonComponent {
private MembersInjector personMembersInjector;
private DaggerPersonComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static PersonComponent create() {
return builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.personMembersInjector = Person_MembersInjector.create(Car_Factory.create());
}
@Override
public void inject(Person person) {
personMembersInjector.injectMembers(person);
}
public static final class Builder {
private Builder() {}
public PersonComponent build() {
return new DaggerPersonComponent(this);
}
}
}
DaggerPersonComponent类实现了我们的 PersonComponent,其通过构建者模式来创建 DaggerPersonComponent 对象,
在该对象构建过程中会调用 initialize(builder) ,该方法利用 Person_MembersInjector.create 来实例化一个 personMembersInjector 对象,至于 personMembersInjector
到底是干嘛的,后面再说。
所以说调用 DaggerPersonComponent.builder().build() 后,其实就是构建一个 DaggerPersonComponent 对象,然后继续调用其 inject 方法来注入依赖。
把 Inject 方法单独提出来看看:
@Override
public void inject(Person person) {
personMembersInjector.injectMembers(person);
}
看到这里,我们知道最后的依赖注入其实是 personMembersInjector.injectMembers(person) 来完成的。
Person_MembersInjector 也为 Dagger 为我们生成的代码:
package com.example.demo_dagger2;
public final class Person_MembersInjector implements MembersInjector {
private final Provider carProvider;
public Person_MembersInjector(Provider carProvider) {
assert carProvider != null;
this.carProvider = carProvider;
}
public static MembersInjector create(Provider carProvider) {
return new Person_MembersInjector(carProvider);
}
@Override
public void injectMembers(Person instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.car = carProvider.get();
}
public static void injectCar(Person instance, Provider carProvider) {
instance.car = carProvider.get();
}
}
injectMembers 方法中对 person 对象进行car对象的注入。
到这里还有一个疑问,Car 对象何时传入到 Person_MembersInjector 中的呢?
上面说过在构建 DaggerPersonComponent 对象过程中,会调用一个 initialize 方法:
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.personMembersInjector = Person_MembersInjector.create(Car_Factory.create());
}
其中 Car_Factory.create() 会为我们生产一个 car 对象,然后 Person_MembersInjector 会存储该 car 对象,以待后面的依赖注入。
Car_Factory 也为 Dagger 为我们自动生成的一个类:
// Generated by dagger.internal.codegen.ComponentProcessor (https://google.github.io/dagger).
package com.example.demo_dagger2;
import dagger.internal.Factory;
public final class Car_Factory implements Factory {
// 饿汉单例,确保线程安全
private static final Car_Factory INSTANCE = new Car_Factory();
@Override
public Car get() {
return new Car();
}
public static Factory create() {
return INSTANCE;
}
/** Proxies {@link Car#Car()}. */
public static Car newCar() {
return new Car();
}
}
DaggerPersonComponent.builder().build().inject(person)
构建 DaggerPersonComponent 对象,即调用 DaggerPersonComponent.builder().build() 方法。
DaggerPersonComponent 对象是基于构建者模式
在构建 DaggerPersonComponent 对象过程中,也会实例化一个 Person_MembersInjector 对象
在实例化 Person_MembersInjector 对象过程中,会保存 Car 的实例,以待后面的依赖的注入
Car 的实例化是通过工厂方法(Car_Factory.create())来完成
牛逼吧~当我们构建 DaggerPersonComponent 对象中,其实也构建了 Person_MembersInjector 对象和依赖对象 car
调用 DaggerPersonComponent 对象的inject方法,将 car 注入到 person 中
调用 DaggerPersonComponent.builder().build() 方法时,通过工厂方法创建Car对象。
Person_MembersInjector 负责将 Car 对象注入到需要该依赖的地方
当我们显示调用 DaggerPersonComponent 对象的inject方法时,DaggerPersonComponent 会用 Person_MembersInjector 来注入car对象
在此案例中:
@injec注释的 Car 构造方法,表明其为一个依赖提供者
在我们的 PersonComponent 接口中定义的 void inject(Person person)方法,表明 Person 为依赖需求者,当然在Person 还需要使用 @Injec 注解其用到的 Car 类型。