Dagger2工作流程分析

TodoFluxArchitecture中使用Dagger2来完成依赖注入工作。Dagger2的上手比较难,深入的理解Dagger2是如何工作实在必行。这边文章主要以TodoFluxArchitecture中如何使用Dagger2做详细的介绍。文章中的代码块中只保留与Dagger2相关代码,如果分析有偏差,欢迎拍砖~~~

技术准备

在Dagger2中,需要使用注解来完成依赖注入,下面是我们在使用过程中总结的每个注解的作用。

@Inject

  • 标注构造方法。当Dagger2需要被@Inject标注的类型完成依赖注入时,便会调用此构造方法,生成对应的对象。如果标注有参数的构造方法,Dagger2会在调用构造方法前,去获得参数对应的对象。所以,@Inject标注有参数构造方法时,需保证所有参数也提供可以被Dagger2调用的构造方法。Dagger2会为@Inject标注的每个类生成相关的Factory类,在Factory类中的get方法完成对象的创建。这一点可以关注文章中的ActionDispatcher,DataDispatcher和TodoStore和他们对应的Factory;
  • 标注成员变量,说明这个成员变量需要Dagger2来通过注入的方式完成初始化,通常在ComeComponent.inject(object)时,自动完成注入。

@Module与@Provide

  • @Module标注类,@Provide标注方法;
  • @Module标注的类对Dagger2提供依赖,该类中@Provider标注的方法必须有返回值,这些方法的返回值是向Dagger2提供的具体依赖;
  • Dagger2通过@Module和@Provider知道在哪里可以找到构造一个对象所需要的依赖;
  • @Provider标注无参数方法时,直接返回已创建或者新创建的对象;
  • @Provider标注有参数方法时,通常返回值是一个接口,参数是这个接口的具体实现类,同时具体实现类需要在构造方法标注@Inject。
  • Dagger2为在Moudle中被@Provider标注的每个方法生成对应的SomeModule_方法名称Factory类,在后面会详细描述这块。

@Named

如果在Module中使用@Provider标注的两个方法返回类型是一样的,这个时候@Named就可以发挥作用啦。Dagger2根据@Named的参数做区分,在Component和@Inject标注的构造方法中,也需要使用@Named标注。使用TodoFluxArchitecture中,在Module中定义了两个返回类型为Dispatcher的方法,具体可参见项目中实现。

@Component

@Component是Dagger2中核心模块,是提供和@Module之间的桥梁,先简单描述@Component的用法,稍后来分析@Component的工作方式。

  • @Component用于标注接口Component;
  • 在Component接口中需要定义无参数只有返回类型的接口方法,如果返回类型相同需要@Named标注方法;
  • 同时还需要定义有参数无返回值的inject接口方法;
  • Dagger2会生成实现Component接口的类DaggerSomeComponent,其中会实现每个在Component中定义的接口方法;
  • 暂时可以先了解这些,后面会更加详细的描述Dagger2通过@Component为我们做了哪些事情。

Module与Component

ApplicationModule和ApplicationComponent是android项目中必不可少的模块和组件,以它们为例来一步一分析。

ApplicationModule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
@Module
public class ApplicationModule {

private final Application app;

/**
* 构造ApplicationModule.
*
* @param application app
*/

public ApplicationModule(Application application) {
this.app = application;
}

/**
* 获得Application.
*
* @return app
*/

@Provides
@Singleton
Application application() {
return app;
}

/**
* 获得Resources.
*
* @return resources
*/

@Provides
@Singleton
Resources resources() {
return app.getResources();
}

/**
* 获得事件分发器.
*
* @param actionDispatcher 事件分发器
* @return actionDispatcher
*/

@Provides
@Singleton
@Named("actionDispatcher")
Dispatcher actionDispatcher(ActionDispatcher actionDispatcher) {
return actionDispatcher;
}

/**
* 获得数据分发器.
*
* @param dataDispatcher 数据分发器
* @return dataDispatcher
*/

@Provides
@Singleton
@Named("dataDispatcher")
Dispatcher dataDispatcher(DataDispatcher dataDispatcher) {
return dataDispatcher;
}

/**
* 获得TodoStore.
*
* @param todoStore store
* @return store
*/

@Provides
@Singleton
Store store(TodoStore todoStore) {
return todoStore;
}


/**
* 获得ActionCreator.
*
* @param todoActionCreator todoActionCreator
* @return ActionCreator
*/

@Provides
@Singleton
ActionCreator actionCreator(TodoActionCreator todoActionCreator) {
return todoActionCreator;
}
}

在ApplicationModule中我们通过@Provider标注了很多方法,每个方法都存在返回值,具有参数的方法返回类型是一个接口,参数类型是对应接口的一种实现类,每个实现类的构造方法需要使用@Inject标注。actionDispatcher和dataDispatcher的返回类型都是Dispatcher,需要使用@Named标注以作区分。

ApplicationComponent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@ForApplication
@Singleton
@Component(
modules = {ApplicationModule.class}
)
public interface ApplicationComponent {

/**
* 注入application.
* @param application application
*/

void inject(Application application);


//暴露给对象图

/**
* 获得Application.
*
* @return Application
*/

Application application();

/**
* 获得Resources.
*
* @return Resources
*/

Resources resources();

/**
* 获得事件分发器.
*
* @return 事件分发器
*/

@Named("actionDispatcher")
Dispatcher actionDispatcher();

/**
* 获得数据分发器.
*
* @return 数据分发器
*/

@Named("dataDispatcher")
Dispatcher dataDispatcher();

/**
* 获得TodoStore.
*
* @return Store
*/

Store store();

/**
* 获得actionCreator.
*
* @return ActionCreator
*/

ActionCreator actionCreator();

/**
* ApplicationComponent的Initializer.
*/

public static final class Initializer {
/**
* 初始化ApplicationComponent.
*
* @param application application
* @return ApplicationComponent
*/

public static ApplicationComponent init(Application application) {
return DaggerApplicationComponent.builder()
.storageComponent(StorageComponent.Initializer.init(application, "aa"))
.applicationModule(new ApplicationModule(application))
.build();
}
}
}

ApplicationComponent接口主要是定义很多接口方法,Dagger2会在具体类中实现每个接口方法,在每个接口方法的实现中完成获得创建的对象,细节稍后会描述。关于静态内部类Initializer是ApplicationComponent对外开放完成依赖注入的工具类。

被依赖类以及对应的Factory

在被依赖类的构造方法添加@Inject后,Dagger2会为被依赖类生成对应的Factory。

被依赖类

ActionDispatcher的相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ActionDispatcher implements Dispatcher {

private Bus bus = new Bus(ThreadEnforcer.MAIN);

/**
* 构造事件分发器.
*/

@Inject
public ActionDispatcher() {
LogTool.debug("构造 ActionDispatcher");
}

...
}

DataDispatcher的相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class DataDispatcher implements Dispatcher {

private Bus bus = new Bus(ThreadEnforcer.MAIN);

/**
* 构造数据分发器.
*/

@Inject
public DataDispatcher() {
LogTool.debug("构造 DataDispatcher");
}

...
}

TodoStore的相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TodoStore implements Store {
private Dispatcher dataDispatcher;
private Dispatcher actionDispatcher;

/**
* 构造TodoStore.
*
* @param dataDispatcher Data Dispatcher
* @param actionDispatcher Action Dispatcher
*/

@Inject
public TodoStore(@Named("dataDispatcher") Dispatcher dataDispatcher,
@Named("actionDispatcher") Dispatcher actionDispatcher) {

LogTool.debug("构造 TodoStore");
this.dataDispatcher = dataDispatcher;
this.actionDispatcher = actionDispatcher;
}
...
}

  • ActionDispatcher和DataDispatcher的构造方法是无参的;
  • TodoStore的构造方法参数分别为actionDispatcher和dataDispatcher,依赖于actionDispatcher和dataDispatcher。

被依赖类对应的Factory

被依赖类对应的Factory

ActionDispatcher对应的Factory:

1
2
3
4
5
6
7
8
9
10
11
12
public enum ActionDispatcher_Factory implements Factory<ActionDispatcher> {
INSTANCE;

@Override
public ActionDispatcher get() {
return new ActionDispatcher();
}

public static Factory<ActionDispatcher> create() {
return INSTANCE;
}
}

DataDispatcher对应的Factory:

1
2
3
4
5
6
7
8
9
10
11
12
public enum DataDispatcher_Factory implements Factory<DataDispatcher> {
INSTANCE;

@Override
public DataDispatcher get() {
return new DataDispatcher();
}

public static Factory<DataDispatcher> create() {
return INSTANCE;
}
}

TodoStore对应的Factory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public final class TodoStore_Factory implements Factory<TodoStore> {
private final Provider<Dispatcher> dataDispatcherProvider;

private final Provider<Dispatcher> actionDispatcherProvider;

public TodoStore_Factory(
Provider<Dispatcher> dataDispatcherProvider, Provider<Dispatcher> actionDispatcherProvider)
{

assert dataDispatcherProvider != null;
this.dataDispatcherProvider = dataDispatcherProvider;
assert actionDispatcherProvider != null;
this.actionDispatcherProvider = actionDispatcherProvider;
}

@Override
public TodoStore get() {
return new TodoStore(dataDispatcherProvider.get(), actionDispatcherProvider.get());
}

public static Factory<TodoStore> create(
Provider<Dispatcher> dataDispatcherProvider, Provider<Dispatcher> actionDispatcherProvider)
{

return new TodoStore_Factory(dataDispatcherProvider, actionDispatcherProvider);
}
}

从ActionDispatcher,DataDispatcher和TodoStore以及对应的Factory代码中,我们可以总结如下:

  • @Inject标注ActionDispatcher和DataDispatcher的构造方法是无参数的;
  • ActionDispatcher_Factory和DataDispatcher_Factory是使用枚举单例模式来创建对应的对象;
  • 在ActionDispatcher_Factory和DataDispatcher_Factory中的get方法中直接创建对应对象返回;
  • @Inject标注TodoStore的构造方法是有参数的,参数是actionDispatcher和dataDispatcher;
  • TodoStore_Factory相对复杂一点,特殊的地方存在两个Provider,dataDispatcherProvider和actionDispatcherProvider;
  • Dagger2为TodoStore生成Factory时,发现TodoStore的构造方法需要参数,Dagger2为两个参数分别生成对应的ProviderProvider由使用Factory的客户传参到Factory;

进一步总结为:

  • 使用@Inject标注被依赖类的无参数构造方法,Dagger2生成的Factory中get方法直接new 被依赖类的对象返回;
  • 使用@Inject标注被依赖类的有参数构造方法,Dagger2生成的Factory创建时,需要提供参数的ProviderProvider为new 被依赖类提供参数;
  • 那么Dagger2如何提供Provider呢?还在在后面详细描述。

Module类方法对应的Factory

Module类方法对应的Factory
通过上图我们可以确定,Dagger2为Module类中的@Provider标注的每个方法生成对应的Factory,Factory的名称规范为SomeModule_方法名称Factory。以application,actionDispatcher方法为例,看看Dagger2生成对应的Factory,主要关注Factory的create和get方法。

application方法对应的Factory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public final class ApplicationModule_ApplicationFactory implements Factory<Application> {
private final ApplicationModule module;

public ApplicationModule_ApplicationFactory(ApplicationModule module) {
assert module != null;
this.module = module;
}

@Override
public Application get() {
return Preconditions.checkNotNull(
module.application(), "Cannot return null from a non-@Nullable @Provides method");
}

public static Factory<Application> create(ApplicationModule module) {
return new ApplicationModule_ApplicationFactory(module);
}
}
create方法:
  • application方法是无参方法,所以只需要ApplicationModule对象module作为参数;
    get方法:
  • 通过module直接获得Application。

actionDispatcher方法对应的Factory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public final class ApplicationModule_ActionDispatcherFactory implements Factory<Dispatcher> {
private final ApplicationModule module;

private final Provider<ActionDispatcher> actionDispatcherProvider;

public ApplicationModule_ActionDispatcherFactory(
ApplicationModule module, Provider<ActionDispatcher> actionDispatcherProvider)
{

assert module != null;
this.module = module;
assert actionDispatcherProvider != null;
this.actionDispatcherProvider = actionDispatcherProvider;
}

@Override
public Dispatcher get() {
return Preconditions.checkNotNull(
module.actionDispatcher(actionDispatcherProvider.get()),
"Cannot return null from a non-@Nullable @Provides method");
}

public static Factory<Dispatcher> create(
ApplicationModule module, Provider<ActionDispatcher> actionDispatcherProvider)
{

return new ApplicationModule_ActionDispatcherFactory(module, actionDispatcherProvider);
}
}
create方法:
  • module和actionDispatcherProvider作为参数。
  • 在actionDispatcher(ActionDispatcher actionDispatcher)方法生成Factory时,Dagger2发现此方法需要参数类型ActionDispatcher的对象,其依赖于外部提供;
  • Provider类型的actionDispatcherProvider由客户使用该Factory时确定。
get方法:
  • 通过actionDispatcherProvider获得具体的ActionDispatcher对象actionDispatcher;
  • 以actionDispatcher作为参数,通过module调用actionDispatcher方法。

Module类方法对应的Factory总结:

关键是在每个Factory的get方法中调用module的对饮的方法,例如ApplicationModule_ApplicationFactory调用module.application()方法,ApplicationModule_ActionDispatcherFactory调用module.actionDispatcher(actionDispatcherProvider.get())方法。

  • 在module中@Provides标注的无参数方法生成的Factory直接通过module调用无参数方法来提供对象;
  • 在module中@Provides标注的有参数方法生成针对接口的Factory,由外部客户提供Provider<> provider提供具体实现类,此时Factory只是对Provider的一种转接。

Module类方法对应的Factory总结图
总结下来,目前Dagger2做了两件事情:

  1. 处理@Inject标注的构造方法,为每个类生成Factory;
  2. 为@Module标注的Module中被@Provides标注的方法,生成对应的Factory;

准备好相关的Factory后,我们来分析在Component中如何使用它们。

Component

Dagger2通过DaggerApplicationComponent实现了ApplicationComponent接口,来分析下DaggerApplicationComponent,在分析前,我们知道注入类FluxApplication的具体实现,同时建议大家再去熟悉下ApplicationComponent接口的定义.

注入的类FluxApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class FluxApplication extends Application {
@Inject
Store todoStore;

@Inject
@Named("dataDispatcher")
Dispatcher dataDispatcher;

@Inject
@Named("actionDispatcher")
Dispatcher actionDispatcher;

@Inject
ActionCreator actionCreator;


private ApplicationComponent component;

@Override
public void onCreate() {
super.onCreate();
String processName = ProcessTool.getProcessName(getApplicationContext());
if (!BuildConfig.APPLICATION_ID.equals(processName)) {
return;
}
initApplication();
}

//初始化Application
private void initApplication() {
initInjector();
}

private void initInjector() {
component = ApplicationComponent.Initializer.init(this);
component.inject(this);
}

/**
* 获得ApplicationComponent.
*
* @return component
*/

public ApplicationComponent getComponent() {
return component;
}
}
  • @Inject标注成员变量,表示Dagger2帮助我们完成成员变量初始化工作;
  • initInjector方法,通过ApplicationComponent.Initializer完成注入操作;
  • 在initInjector方法调用后,便可以使用@Inject标注成员变量完成相关的业务操作.

生成的DaggerSomeComponent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
public final class DaggerApplicationComponent implements ApplicationComponent {
private Provider<Dispatcher> dataDispatcherProvider;

private Provider<Dispatcher> actionDispatcherProvider;

private Provider<TodoStore> todoStoreProvider;

private Provider<Store> storeProvider;

private Provider<TodoActionCreator> todoActionCreatorProvider;

private Provider<ActionCreator> actionCreatorProvider;

private MembersInjector<FluxApplication> fluxApplicationMembersInjector;

private Provider<Application> applicationProvider;

private Provider<Resources> resourcesProvider;

private DaggerApplicationComponent(Builder builder) {
assert builder != null;
initialize(builder);
}

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

@SuppressWarnings("unchecked")
private void initialize(final Builder builder) {

this.dataDispatcherProvider =
ScopedProvider.create(
ApplicationModule_DataDispatcherFactory.create(
builder.applicationModule, DataDispatcher_Factory.create()));

this.actionDispatcherProvider =
ScopedProvider.create(
ApplicationModule_ActionDispatcherFactory.create(
builder.applicationModule, ActionDispatcher_Factory.create()));

this.todoStoreProvider =
TodoStore_Factory.create(dataDispatcherProvider, actionDispatcherProvider);

this.storeProvider =
ScopedProvider.create(
ApplicationModule_StoreFactory.create(builder.applicationModule, todoStoreProvider));

this.todoActionCreatorProvider =
TodoActionCreator_Factory.create(actionDispatcherProvider, briteDatabaseProvider);

this.actionCreatorProvider =
ScopedProvider.create(
ApplicationModule_ActionCreatorFactory.create(
builder.applicationModule, todoActionCreatorProvider));

this.fluxApplicationMembersInjector =
FluxApplication_MembersInjector.create(
storeProvider, dataDispatcherProvider, actionDispatcherProvider, actionCreatorProvider);

this.applicationProvider =
ScopedProvider.create(
ApplicationModule_ApplicationFactory.create(builder.applicationModule));

this.resourcesProvider =
ScopedProvider.create(ApplicationModule_ResourcesFactory.create(builder.applicationModule));
}

@Override
public void inject(FluxApplication application) {
fluxApplicationMembersInjector.injectMembers(application);
}

@Override
public Application application() {
return applicationProvider.get();
}

@Override
public Resources resources() {
return resourcesProvider.get();
}

@Override
public Dispatcher actionDispatcher() {
return actionDispatcherProvider.get();
}

@Override
public Dispatcher dataDispatcher() {
return dataDispatcherProvider.get();
}

@Override
public Store store() {
return storeProvider.get();
}

@Override
public ActionCreator actionCreator() {
return actionCreatorProvider.get();
}

public static final class Builder {
private ApplicationModule applicationModule;

private StorageComponent storageComponent;

private Builder() {}

public ApplicationComponent build() {
if (applicationModule == null) {
throw new IllegalStateException(
ApplicationModule.class.getCanonicalName() + " must be set");
}
return new DaggerApplicationComponent(this);
}

public Builder applicationModule(ApplicationModule applicationModule) {
this.applicationModule = Preconditions.checkNotNull(applicationModule);
return this;
}
}
}
  • DaggerApplicationComponent是ApplicationComponent接口的实现类;
  • DaggerApplicationComponent通过Builder模式完成创建;
  • 在initialize时,会初始化Module类方法对应的Factory;
  • Module中有参数方法的Module类方法对应的Factory需要被依赖类以及对应的Factory作为Provider参数完成create;
  • 每个实现的接口方法中,使用Module类方法对应的Factory来完成具体的实现;
  • 根据FluxApplication中@Inject标注的成员变量生成fluxApplicationMembersInjector;
  • fluxApplicationMembersInjector.injectMembers(application)完成@Inject标注的成员变量的初始化,具体可参见FluxApplicationMembersInjectorF的具体实现.

Dagger2 到底做了些什么事情

下面是我总结的流程图:

  1. 为@Inject构造方法的类,我称呼为被注入类,生成对应的Factory,构造方法的参数也需要标注@Inject,也会生成对应的Factory;
  2. 为@Inject标注成员变量的类,称呼为注入类,生成对应的MembersInjector类,实际上是在MembersInjector类中完成对成员变量的初始化;
  3. 为Module中@Provides方法生成Factory;
  4. 为Component生成DaggerSomeComponent,在DaggerSomeComponent中,使用1和3中生成的Factory作为对象提供者,使用2中的MembersInjector完成对象初始化.

本篇文章是通过Dagger2生成的代码来分析Dagger2如何完成依赖注入,描述了最简单情况的整个流程.在实际项目中,可能存在Scope,Component依赖,Component与Module一对多等情况,通过分析生成的代码,可以很快了解它们如何发挥作用.