Dagger2 源码分析
Dagger简单介绍
Dagger2涉及到依赖注入,有关依赖注入的请到
理解依赖注入
通过注解方式实现依赖注入分为两种:
- 在运行时读取注解来实现依赖注入,依赖的生成和注入需要依靠 Java 的反射机制。
- 通过apt插件在编译阶段生成注入代码。
Dagger2是属于后者,反射只是在编译阶段使用了,而在应用运行的时候其实运行的是真正的Java代码并没有涉及到注解反射。
本文用一个极简的demo来说明Dagger原理,不去结合MVP模式使用Dagger方式,我自己认为这样会更加的复杂。
Dagger编译阶段到底干了什么?
有一个超简单的demo只有三个类分别是:MainActivity、MainComponent和PersonBean。
三个类之间的关系Demo代码
public class PersonBean {
public String name;
@Inject
public PersonBean(){
}
}
@Component
public interface MainComponent {
void inject(MainActivity activity);
}
写好PersonBean、MainComponent 代码后,使用as的build->make project,会生成DaggerMainComponent,在MainActivity上使用
public class MainActivity extends AppCompatActivity {
@Inject
PersonBean personBean;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder().build().inject(this);
}
}
上面使用了as的build->make project后,会在app/build/generated/source/apt目录下生成对应的注入代码。
PersonBean - 》 PersonBean_Factory
public enum PersonBean_Factory implements Factory<PersonBean> {
INSTANCE;
@Override
public PersonBean get() {
return new PersonBean();
}
public static Factory<PersonBean> create() {
return INSTANCE;
}
}
通过上面代码直观的看到PersonBean_Factory有两个方法:
-
get()
在该方法中初始化了目标类需要依赖的PersonBean对象。 -
create()
在该方法返回了PersonBean_Factory本类的实例。
MainComponent-》DaggerMainComponent
public final class DaggerMainComponent implements MainComponent {
private MembersInjector<MainActivity> mainActivityMembersInjector;
private DaggerMainComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
public static Builder builder() {
return new Builder();
}
public static MainComponent create() {
return builder().build();
}
@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {
this.mainActivityMembersInjector =
MainActivity_MembersInjector.create(PersonBean_Factory.create());
}
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
public static final class Builder {
private Builder() {}
public MainComponent build() {
return new DaggerMainComponent(this);
}
}
}
通过上面代码直观的看到:
- DaggerMainComponent对象是通过设计模式之构造器模式创建的
- DaggerMainComponent实现了MainComponent接口并实现了其中的inject()方法。
MainActivity -》MainActivity_MembersInjector
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
private final Provider<PersonBean> personBeanProvider;
public MainActivity_MembersInjector(Provider<PersonBean> personBeanProvider) {
assert personBeanProvider != null;
this.personBeanProvider = personBeanProvider;
}
public static MembersInjector<MainActivity> create(Provider<PersonBean> personBeanProvider) {
return new MainActivity_MembersInjector(personBeanProvider);
}
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.personBean = personBeanProvider.get();
}
public static void injectPersonBean(
MainActivity instance, Provider<PersonBean> personBeanProvider) {
instance.personBean = personBeanProvider.get();
}
}
这里我们就有一些疑问:
我们通过编译期间生成的这些类
- 这些类之间的关系是怎样的?
- 这些类中的方法如何被调用?
- 一个完成的注入过程是怎么的?
首先第一个问题,这些类之间的关系是怎样的?请看下面的UML类图
Dagger的UML类图上面的第二三疑问,通过接下来分析dagger2依赖注入过程来理解,也就是代码执行流程。
dagger2依赖注入过程
DaggerMainComponent.builder().build().inject(this);
首先我们从这一句代码为切入点,来学习dagger2依赖注入过程。
-
DaggerMainComponent.builder()
创建一个DaggerMainComponent内部的Builder对象并返回它。 -
DaggerMainComponent.builder().build()
创建一个DaggerMainComponent对象并返回它。这里我们知道DaggerMainComponent对象的实例化是通过构造器模式被创建的。
DaggerMainComponent构造方法
private DaggerMainComponent(Builder builder) {
assert builder != null;
initialize(builder);
}
private void initialize(final Builder builder) {
this.mainActivityMembersInjector =
MainActivity_MembersInjector.create(PersonBean_Factory.create());
}
DaggerMainComponent构造函数干了这些事情:
- 调用PersonBean_Factory.create()得到PersonBean_Factory对象,然后把此对象作为参数传入MainActivity_MembersInjector.create(...),然后MainActivity_MembersInjector.create方法创建
MainActivity_MembersInjector实例对象并赋值,那么
DaggerMainComponent就关联上了它。
4.DaggerMainComponent.builder().build().inject(this);
实际上是调用DaggerMainComponent.inject方法
@Override
public void inject(MainActivity activity) {
mainActivityMembersInjector.injectMembers(activity);
}
在这方法中使用在DaggerMainComponent构造方法中注入的MainActivity_MembersInjector对象,并调用其injectMembers方法。
@Override
public void injectMembers(MainActivity instance) {
if (instance == null) {
throw new NullPointerException("Cannot inject members into a null reference");
}
instance.personBean = personBeanProvider.get();
}
instance.personBean = personBeanProvider.get();这段代码很关键,目标类MainActivity依赖的类PersonBean就是在这时候被赋值的。personBeanProvider其实就是PersonBean_Factory。
personBeanProvider.get()代码如下:
@Override
public PersonBean get() {
return new PersonBean();
}
该方法创建一个被依赖的对象PersonBean并返回。
这里我们就了解了Dagger2的依赖注入过程。