ARouter源码解析:complier

今天这篇文章,我们就来分析编译时的arouter-complier的实现,看一下映射文件是如何生成的。

基础知识

按照注解的处理时期,分为两种类型:运行时和编译时,运行时注解处理会引起性能问题,编译时注解依赖APT(Annotation Processing Tools)实现,其原理是在类、函数、字段上添加注解,在编译时,编译器会去检查AbstractProcessor的子类,并调用它实现的process函数,然后将添加了注解的所有元素都传递到process函数中,使得开发人员可以在编译期进行处理,主要就是生成新的Java类。

ProcessingEnvironment

用于提供实用的工具类,主要是Elements、Types和Filer这三个。

Elements

用来处理Element的工具类,源码中的每个部分都是Element的一个特定类型,其代码程序中的元素,例如包、类、方法,每一个元素代表一个静态的,语言级别的结构,Element是一个interface。

根据类、成员变量等不同,有如下的继承接口 & 实现类:

Types

用来处理TypeMirror的工具类。从Element的实现类中,例如TypeElement,我们可以获取类的名称,但你不能获取类的信息,可以通过element.asType()来获取一个Element的TypeMirror,然后获取类的信息。

Filer

用来创建文件。
我们在 创建映射文件 的时候,包括以下几步,后一步的结果依赖于前一步:

  • 函数形参的类型,使用ParameterizedTypeName。
  • 函数形参的类型 & 名称,使用ParameterSpec。
  • 函数的声明,使用MethodSpec.Builder。
  • 类的声明,使用JavaFile.builder,最后调用JavaFile的writeTo(mFiler)方法写入到磁盘当中,这里的mFiler就是通过ProcessingEnvironment获取到的。

@Route 注解的解析

下面是对于RouteProcessor的 解析,详细的可以看注释里面的说明。

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
/**
* A processor used for find route.
*
* @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
* @version 1.0
* @since 16/8/15 下午10:08
*/
@AutoService(Processor.class)
@SupportedOptions(KEY_MODULE_NAME)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes({ANNOTATION_TYPE_ROUTE, ANNOTATION_TYPE_AUTOWIRED})
public class RouteProcessor extends AbstractProcessor {

/**
* 以组为 key,value 对应于该组下解析出的所有注解信息,Set 的实现为 TreeSet,会根据 path 来进行排序。
*/
private Map<String, Set<RouteMeta>> groupMap = new HashMap<>();

/**
* 以根节点为 key,value 对应于创建的文件。
*/
private Map<String, String> rootMap = new TreeMap<>();
private Filer mFiler;
private Logger logger;
private Types types;
private Elements elements;
private TypeUtils typeUtils;
private String moduleName = null;
private TypeMirror iProvider = null;

/**
* 通过 ProcessingEnvironment 初始化后面需要使用到的工具类,例如 Filer,Types 和 Elements。
* @param processingEnv 提供解析注解所需的工具类。
*/
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);

//Filer:用于创建 Java 文件的工具类。
mFiler = processingEnv.getFiler();
//Types:用于操作类型的工具类。
types = processingEnv.getTypeUtils();
//Elements:用于处理 Element 的工具类。
elements = processingEnv.getElementUtils();

//将两个工具类进行封装。
typeUtils = new TypeUtils(types, elements);
//日志工具类。
logger = new Logger(processingEnv.getMessager());

//解析我们在 android 节点下配置的 moduleName,其为对应模块的名字。
Map<String, String> options = processingEnv.getOptions();
if (MapUtils.isNotEmpty(options)) {
moduleName = options.get(KEY_MODULE_NAME);
}

//对 moduleName 进行处理。
if (StringUtils.isNotEmpty(moduleName)) {
moduleName = moduleName.replaceAll("[^0-9a-zA-Z_]+", "");
logger.info("The user has configuration the module name, it was [" + moduleName + "]");
//如果没有配置 moduleName,那么会抛出异常。
} else {
logger.error("These no module name, at 'build.gradle', like :\n" +
"apt {\n" +
" arguments {\n" +
" moduleName project.getName();\n" +
" }\n" +
"}\n");
throw new RuntimeException("ARouter::Compiler >>> No module name, for more information, look at gradle log.");
}

//获取 IProvider 的 TypeMirror,它包含了 IProvider 的所有信息。
iProvider = elements.getTypeElement(Consts.IPROVIDER).asType();

logger.info(">>> RouteProcessor init. <<<");
}

/**
* {@inheritDoc}
*
* @param annotations
* @param roundEnv
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (CollectionUtils.isNotEmpty(annotations)) {
//获得所有被 @Route 注解的元素。
Set<? extends Element> routeElements = roundEnv.getElementsAnnotatedWith(Route.class);
try {
logger.info(">>> Found routes, start... <<<");
//开始处理。
this.parseRoutes(routeElements);

} catch (Exception e) {
logger.error(e);
}
return true;
}

return false;
}

private void parseRoutes(Set<? extends Element> routeElements) throws IOException {
if (CollectionUtils.isNotEmpty(routeElements)) {

logger.info(">>> Found routes, size is " + routeElements.size() + " <<<");
//清空信息。
rootMap.clear();

//1.获得 Activity、Service、Fragment 和 FragmentV4 的信息,这些是定义在 Android SDK 当中的。
TypeMirror type_Activity = elements.getTypeElement(ACTIVITY).asType();
TypeMirror type_Service = elements.getTypeElement(SERVICE).asType();
TypeMirror fragmentTm = elements.getTypeElement(FRAGMENT).asType();
TypeMirror fragmentTmV4 = elements.getTypeElement(Consts.FRAGMENT_V4).asType();

//2.获得 IRouteGroup 和 IProviderGroup 的信息,这些接口是定义在 arouter-api 当中的模板。
TypeElement type_IRouteGroup = elements.getTypeElement(IROUTE_GROUP);
TypeElement type_IProviderGroup = elements.getTypeElement(IPROVIDER_GROUP);

//3.RouteMeta 和 RouteType 的信息。
ClassName routeMetaCn = ClassName.get(RouteMeta.class);
ClassName routeTypeCn = ClassName.get(RouteType.class);

//4. 定义函数形参的类型为 Map<String, Class<? extends IRouteGroup>>。
ParameterizedTypeName inputMapTypeOfRoot = ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(String.class),
ParameterizedTypeName.get(
ClassName.get(Class.class),
WildcardTypeName.subtypeOf(ClassName.get(type_IRouteGroup))
)
);

//5. 定义函数形参的类型为 Map<String, RouteMeta>。
ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(String.class),
ClassName.get(RouteMeta.class)
);

//6. 定义函数的形参类型 & 形参名字。
//6.1 Map<String, Class<? extends IRouteGroup>> routes
ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, "routes").build();
//6.2 Map<String, RouteMeta> atlas
ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "atlas").build();
//6.3 Map<String, RouteMeta> providers
ParameterSpec providerParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "providers").build();

//7.定义函数的声明为 public void loadInto(Map<String, Class<? extends IRouteGroup>> routes)。
MethodSpec.Builder loadIntoMethodOfRootBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(rootParamSpec);

//8.遍历所有的被 @Route 注解的 Element
for (Element element : routeElements) {
//获得该元素的类型信息。
TypeMirror tm = element.asType();
//获得该元素的注解。
Route route = element.getAnnotation(Route.class);
RouteMeta routeMeta = null;
//Activity 的子类。
if (types.isSubtype(tm, type_Activity)) {
logger.info(">>> Found activity route: " + tm.toString() + " <<<");
Map<String, Integer> paramsType = new HashMap<>();
//获得其所有被 @Autowired 注解的成员变量。
for (Element field : element.getEnclosedElements()) {
//不处理 IProvider 的子类。
if (field.getKind().isField() && field.getAnnotation(Autowired.class) != null && !types.isSubtype(field.asType(), iProvider)) {
Autowired paramConfig = field.getAnnotation(Autowired.class);
//将所有被 @Autowired 注解的相关信息放到 map 当中。
paramsType.put(StringUtils.isEmpty(paramConfig.name()) ? field.getSimpleName().toString() : paramConfig.name(), typeUtils.typeExchange(field));
}
}
routeMeta = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType);
//IProvider 的子类。
} else if (types.isSubtype(tm, iProvider)) {
logger.info(">>> Found provider route: " + tm.toString() + " <<<");
routeMeta = new RouteMeta(route, element, RouteType.PROVIDER, null);
//Service 的子类。
} else if (types.isSubtype(tm, type_Service)) {
logger.info(">>> Found service route: " + tm.toString() + " <<<");
routeMeta = new RouteMeta(route, element, RouteType.parse(SERVICE), null);
//Fragment 或者 FragmentV4 的子类。
} else if (types.isSubtype(tm, fragmentTm) || types.isSubtype(tm, fragmentTmV4)) {
logger.info(">>> Found fragment route: " + tm.toString() + " <<<");
routeMeta = new RouteMeta(route, element, RouteType.parse(FRAGMENT), null);
} else {
throw new RuntimeException("ARouter::Compiler >>> Found unsupported class type, type = [" + types.toString() + "].");
}
//对其按 group 进行分组。
categories(routeMeta);
}

//9. 定义函数的声明为 public void loadInto(Map<String, RouteMeta> providers)。
MethodSpec.Builder loadIntoMethodOfProviderBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(providerParamSpec);

//10. 创建 Java 源代码,遍历所有的 group。
for (Map.Entry<String, Set<RouteMeta>> entry : groupMap.entrySet()) {
String groupName = entry.getKey();

//定义函数的声明为 public void loadInto(Map<String, RouteMeta> atlas)。
MethodSpec.Builder loadIntoMethodOfGroupBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(groupParamSpec);

//遍历该 group 下所有的 RouteMeta。
Set<RouteMeta> groupData = entry.getValue();

for (RouteMeta routeMeta : groupData) {
switch (routeMeta.getType()) {
//填充函数体。
case PROVIDER:
List<? extends TypeMirror> interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces();
for (TypeMirror tm : interfaces) {
//IProvider。
if (types.isSameType(tm, iProvider)) {
//添加 providers.put(..) 函数体。
loadIntoMethodOfProviderBuilder.addStatement(
"providers.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, null, " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))",
(routeMeta.getRawType()).toString(),
routeMetaCn,
routeTypeCn,
ClassName.get((TypeElement) routeMeta.getRawType()),
routeMeta.getPath(),
routeMeta.getGroup());
//IProvider 的子类。
} else if (types.isSubtype(tm, iProvider)) {
//添加 providers.put(..) 函数体。
loadIntoMethodOfProviderBuilder.addStatement(
"providers.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, null, " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))",
tm.toString(),
routeMetaCn,
routeTypeCn,
ClassName.get((TypeElement) routeMeta.getRawType()),
routeMeta.getPath(),
routeMeta.getGroup());
}
}
break;
default:
break;
}

StringBuilder mapBodyBuilder = new StringBuilder();
Map<String, Integer> paramsType = routeMeta.getParamsType();
if (MapUtils.isNotEmpty(paramsType)) {
for (Map.Entry<String, Integer> types : paramsType.entrySet()) {
mapBodyBuilder.append("put(\"").append(types.getKey()).append("\", ").append(types.getValue()).append("); ");
}
}
String mapBody = mapBodyBuilder.toString();
//填充函数体。
loadIntoMethodOfGroupBuilder.addStatement(
"atlas.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, " + (StringUtils.isEmpty(mapBody) ? null : ("new java.util.HashMap<String, Integer>(){{" + mapBodyBuilder.toString() + "}}")) + ", " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))",
routeMeta.getPath(),
routeMetaCn,
routeTypeCn,
ClassName.get((TypeElement) routeMeta.getRawType()),
routeMeta.getPath().toLowerCase(),
routeMeta.getGroup().toLowerCase());
}

//关键点1:每一个 group 创建一个 Java 文件,其类名为 Arouter$$Group$$组名,函数名为 public void loadInto(Map<String, RouteMeta> atlas)
String groupFileName = NAME_OF_GROUP + groupName;
JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
TypeSpec.classBuilder(groupFileName)
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(type_IRouteGroup))
.addModifiers(PUBLIC)
.addMethod(loadIntoMethodOfGroupBuilder.build())
.build()
).build().writeTo(mFiler);

logger.info(">>> Generated group: " + groupName + "<<<");
rootMap.put(groupName, groupFileName);
}

if (MapUtils.isNotEmpty(rootMap)) {
for (Map.Entry<String, String> entry : rootMap.entrySet()) {
loadIntoMethodOfRootBuilder.addStatement("routes.put($S, $T.class)", entry.getKey(), ClassName.get(PACKAGE_OF_GENERATE_FILE, entry.getValue()));
}
}

//关键点2:创建 Java 文件,类名为 Arouter$$Providers$$moduleName,函数名为 public void loadInto(Map<String, RouteMeta> providers),存放 PROVIDER 类型的节点。
String providerMapFileName = NAME_OF_PROVIDER + SEPARATOR + moduleName;
JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
TypeSpec.classBuilder(providerMapFileName)
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(type_IProviderGroup))
.addModifiers(PUBLIC)
.addMethod(loadIntoMethodOfProviderBuilder.build())
.build()
).build().writeTo(mFiler);

logger.info(">>> Generated provider map, name is " + providerMapFileName + " <<<");

//关键点3:创建 Java 文件,类名为 Arouter$$Root$$moduleName,函数名为 public void loadInto(Map<String, Class<? extends IRouteGroup>> routes)
String rootFileName = NAME_OF_ROOT + SEPARATOR + moduleName;
JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
TypeSpec.classBuilder(rootFileName)
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(elements.getTypeElement(ITROUTE_ROOT)))
.addModifiers(PUBLIC)
.addMethod(loadIntoMethodOfRootBuilder.build())
.build()
).build().writeTo(mFiler);

logger.info(">>> Generated root, name is " + rootFileName + " <<<");
}
}

/**
* 对 @Route 注解的类进行分类。
* @param routeMete
*/
private void categories(RouteMeta routeMete) {
if (routeVerify(routeMete)) {
logger.info(">>> Start categories, group = " + routeMete.getGroup() + ", path = " + routeMete.getPath() + " <<<");
Set<RouteMeta> routeMetas = groupMap.get(routeMete.getGroup());
if (CollectionUtils.isEmpty(routeMetas)) {
Set<RouteMeta> routeMetaSet = new TreeSet<>(new Comparator<RouteMeta>() {
@Override
public int compare(RouteMeta r1, RouteMeta r2) {
try {
return r1.getPath().compareTo(r2.getPath());
} catch (NullPointerException npe) {
logger.error(npe.getMessage());
return 0;
}
}
});
routeMetaSet.add(routeMete);
groupMap.put(routeMete.getGroup(), routeMetaSet);
} else {
routeMetas.add(routeMete);
}
} else {
logger.warning(">>> Route meta verify error, group is " + routeMete.getGroup() + " <<<");
}
}

/**
* 验证 RouteMeta,要求 @Route 指定的 name 不为空,并且要使用 / 作为开头。
*
* 并解析 RouteMeta 中的 group,默认是使用 / 后的第一个字段,如果指定了 group,那么就使用 group 的值。
* @param meta
* @return 验证正确。
*/
private boolean routeVerify(RouteMeta meta) {
String path = meta.getPath();

if (StringUtils.isEmpty(path) || !path.startsWith("/")) {
return false;
}

if (StringUtils.isEmpty(meta.getGroup())) {
try {
String defaultGroup = path.substring(1, path.indexOf("/", 1));
if (StringUtils.isEmpty(defaultGroup)) {
return false;
}

meta.setGroup(defaultGroup);
return true;
} catch (Exception e) {
logger.error("Failed to extract default group! " + e.getMessage());
return false;
}
}

return true;
}
}

大家注意看上面的三个关键点,其最终目的就是创建三个Java文件,对于第一章中的module-other,就是创建了下面三个文件:

  • ARouter$$Root$$ + 模块名,由于Arouter对于一个模块下的所有组件都是 采用分组加载 的机制,因此该文件存储的是组名,对应的value为该组下所有的组件。
1
2
3
4
5
6
7
8
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Root$$moduleother implements IRouteRoot {
@Override
public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
routes.put("other", ARouter$$Group$$other.class);
}
}
  • ARouter$$Group$$ + 组名:对应该组下所有的组件,可以看到这里面包含了@Route中的path对应的组件的映射,这些信息都保存在RouteMeta当中。
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Group$$other implements IRouteGroup {
@Override
public void loadInto(Map<String, RouteMeta> atlas) {
atlas.put("/other/event_bus", RouteMeta.build(RouteType.ACTIVITY, EventBusActivity.class, "/other/event_bus", "other", null, -1, -2147483648));
atlas.put("/other/inject", RouteMeta.build(RouteType.ACTIVITY, InjectActivity.class, "/other/inject", "other", new java.util.HashMap<String, Integer>(){{put("inject_object", 10); put("inject_age", 3); }}, -1, -2147483648));
atlas.put("/other/inter_middle", RouteMeta.build(RouteType.ACTIVITY, InterMiddleActivity.class, "/other/inter_middle", "other", null, -1, -2147483648));
atlas.put("/other/inter_target", RouteMeta.build(RouteType.ACTIVITY, InterTargetActivity.class, "/other/inter_target", "other", null, -1, 2));
atlas.put("/other/no_result", RouteMeta.build(RouteType.ACTIVITY, NoResultActivity.class, "/other/no_result", "other", null, -1, -2147483648));
atlas.put("/other/result_server", RouteMeta.build(RouteType.ACTIVITY, ResultServerActivity.class, "/other/result_server", "other", null, -1, -2147483648));
}
}
  • Arouter$$Providers$$ + 模块名:对应于该模块下所有IProvider的子类。
1
2
3
4
5
6
7
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Providers$$moduleother implements IProviderGroup {
@Override
public void loadInto(Map<String, RouteMeta> providers) {
}
}

@Interceptor 注解的解析

@Interceptor注解的解析是通过InterceptorProcessor处理的,其说明如下面代码的注释,原理和2.2中@Route相同,最终的目标也是创建Java文件。

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
@AutoService(Processor.class)
@SupportedOptions(KEY_MODULE_NAME)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes(ANNOTATION_TYPE_INTECEPTOR)
public class InterceptorProcessor extends AbstractProcessor {
private Map<Integer, Element> interceptors = new TreeMap<>();
private Filer mFiler; // File util, write class file into disk.
private Logger logger;
private Elements elementUtil;
private String moduleName = null; // Module name, maybe its 'app' or others
private TypeMirror iInterceptor = null;

@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);

//工具类。
mFiler = processingEnv.getFiler(); // Generate class.
elementUtil = processingEnv.getElementUtils(); // Get class meta.
logger = new Logger(processingEnv.getMessager()); // Package the log utils.

//获取模块名。
Map<String, String> options = processingEnv.getOptions();
if (MapUtils.isNotEmpty(options)) {
moduleName = options.get(KEY_MODULE_NAME);
}

if (StringUtils.isNotEmpty(moduleName)) {
moduleName = moduleName.replaceAll("[^0-9a-zA-Z_]+", "");
logger.info("The user has configuration the module name, it was [" + moduleName + "]");
} else {
logger.error("These no module name, at 'build.gradle', like :\n" +
"apt {\n" +
" arguments {\n" +
" moduleName project.getName();\n" +
" }\n" +
"}\n");
throw new RuntimeException("ARouter::Compiler >>> No module name, for more information, look at gradle log.");
}

//获得 IInterceptor 的类信息。
iInterceptor = elementUtil.getTypeElement(Consts.IINTERCEPTOR).asType();

logger.info(">>> InterceptorProcessor init. <<<");
}

/**
* 系统调用的处理类。
* @param annotations 所有被注解的元素。
* @param roundEnv 运行时环境。
* @return 是否成功处理。
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (CollectionUtils.isNotEmpty(annotations)) {
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Interceptor.class);
try {
parseInterceptors(elements);
} catch (Exception e) {
logger.error(e);
}
return true;
}

return false;
}

/**
* 解析注解,创建 JavaFile
* @param elements 所有被 @Interceptor 注解的元素。
* @throws IOException 抛出异常。
*/
private void parseInterceptors(Set<? extends Element> elements) throws IOException {
if (CollectionUtils.isNotEmpty(elements)) {
logger.info(">>> Found interceptors, size is " + elements.size() + " <<<");

//1.遍历所有被 @Interceptor 注解的元素。
for (Element element : elements) {
//必须要实现 IInterceptor 接口。
if (verify(element)) {
logger.info("A interceptor verify over, its " + element.asType());
Interceptor interceptor = element.getAnnotation(Interceptor.class);
//按照优先级作为 key,存储到 map 当中,必须要保证一个模块内的优先级不会重复,否则会抛出异常。
Element lastInterceptor = interceptors.get(interceptor.priority());
if (null != lastInterceptor) { // Added, throw exceptions
throw new IllegalArgumentException(
String.format(Locale.getDefault(), "More than one interceptors use same priority [%d], They are [%s] and [%s].",
interceptor.priority(),
lastInterceptor.getSimpleName(),
element.getSimpleName())
);
}

interceptors.put(interceptor.priority(), element);
} else {
logger.error("A interceptor verify failed, its " + element.asType());
}
}

TypeElement type_ITollgate = elementUtil.getTypeElement(IINTERCEPTOR);
TypeElement type_ITollgateGroup = elementUtil.getTypeElement(IINTERCEPTOR_GROUP);

//2.函数形参的类型为 Map<Integer, Class<? extends IInterceptor>>
ParameterizedTypeName inputMapTypeOfTollgate = ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(Integer.class),
ParameterizedTypeName.get(
ClassName.get(Class.class),
WildcardTypeName.subtypeOf(ClassName.get(type_ITollgate))
)
);

//3.函数形参的类型 & 名字为 Map<Integer, Class<? extends IInterceptor>> interceptors
ParameterSpec tollgateParamSpec = ParameterSpec.builder(inputMapTypeOfTollgate, "interceptors").build();

//4.函数名为 loadInto
MethodSpec.Builder loadIntoMethodOfTollgateBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(tollgateParamSpec);

//5.利用前面遍历出来的列表,填充函数体。
if (null != interceptors && interceptors.size() > 0) {
// Build method body
for (Map.Entry<Integer, Element> entry : interceptors.entrySet()) {
loadIntoMethodOfTollgateBuilder.addStatement("interceptors.put(" + entry.getKey() + ", $T.class)", ClassName.get((TypeElement) entry.getValue()));
}
}

//6.关键点:写入 JavaFile,类名为 Arouter$$Interceptors$$moduleName
JavaFile.builder(PACKAGE_OF_GENERATE_FILE,
TypeSpec.classBuilder(NAME_OF_INTERCEPTOR + SEPARATOR + moduleName)
.addModifiers(PUBLIC)
.addJavadoc(WARNING_TIPS)
.addMethod(loadIntoMethodOfTollgateBuilder.build())
.addSuperinterface(ClassName.get(type_ITollgateGroup))
.build()
).build().writeTo(mFiler);

logger.info(">>> Interceptor group write over. <<<");
}
}

/**
* 验证,必须要保证实现了 IInterceptor 接口。
* @param element 元素。
* @return 验证陈宫。
*/
private boolean verify(Element element) {
Interceptor interceptor = element.getAnnotation(Interceptor.class);
// It must be implement the interface IInterceptor and marked with annotation Interceptor.
return null != interceptor && ((TypeElement) element).getInterfaces().contains(iInterceptor);
}
}

最终会创建Java文件。

其命名的规则为:Arouter$$Interceptors + 模块名。

1
2
3
4
5
6
7
8
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Interceptors$$libbase implements IInterceptorGroup {
@Override
public void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptors) {
interceptors.put(1, BaseInterceptor.class);
}
}

@Autowired 注解的解析

@Autowired注解的解析依赖于AutowiredProcessor,它的原理和上面类似,都是最终创建一个JavaFile:

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
@AutoService(Processor.class)
@SupportedOptions(KEY_MODULE_NAME)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes({ANNOTATION_TYPE_AUTOWIRED})
public class AutowiredProcessor extends AbstractProcessor {
private Filer mFiler; // File util, write class file into disk.
private Logger logger;
private Types types;
private TypeUtils typeUtils;
private Elements elements;
private Map<TypeElement, List<Element>> parentAndChild = new HashMap<>(); // Contain field need autowired and his super class.
private static final ClassName ARouterClass = ClassName.get("com.alibaba.android.arouter.launcher", "ARouter");
private static final ClassName AndroidLog = ClassName.get("android.util", "Log");

@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);

mFiler = processingEnv.getFiler(); // Generate class.
types = processingEnv.getTypeUtils(); // Get type utils.
elements = processingEnv.getElementUtils(); // Get class meta.

typeUtils = new TypeUtils(types, elements);

logger = new Logger(processingEnv.getMessager()); // Package the log utils.

logger.info(">>> AutowiredProcessor init. <<<");
}

@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
if (CollectionUtils.isNotEmpty(set)) {
try {
logger.info(">>> Found autowired field, start... <<<");
categories(roundEnvironment.getElementsAnnotatedWith(Autowired.class));
generateHelper();

} catch (Exception e) {
logger.error(e);
}
return true;
}

return false;
}

/**
* 开始进行解析。
* @throws IOException IO 异常。
* @throws IllegalAccessException 不满足状态的异常。
*/
private void generateHelper() throws IOException, IllegalAccessException {
TypeElement type_ISyringe = elements.getTypeElement(ISYRINGE);
TypeElement type_JsonService = elements.getTypeElement(JSON_SERVICE);
TypeMirror iProvider = elements.getTypeElement(Consts.IPROVIDER).asType();
TypeMirror activityTm = elements.getTypeElement(Consts.ACTIVITY).asType();
TypeMirror fragmentTm = elements.getTypeElement(Consts.FRAGMENT).asType();
TypeMirror fragmentTmV4 = elements.getTypeElement(Consts.FRAGMENT_V4).asType();

//1. 函数的形参类型为 Object,形参名为 target。
ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build();

//2.遍历所有拥有 @Autowired 注解的元素。
if (MapUtils.isNotEmpty(parentAndChild)) {
for (Map.Entry<TypeElement, List<Element>> entry : parentAndChild.entrySet()) {
//2.1 方法名为 inject
MethodSpec.Builder injectMethodBuilder = MethodSpec.methodBuilder(METHOD_INJECT)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(objectParamSpec);

TypeElement parent = entry.getKey();
List<Element> childs = entry.getValue();

String qualifiedName = parent.getQualifiedName().toString();
String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
String fileName = parent.getSimpleName() + NAME_OF_AUTOWIRED;

logger.info(">>> Start process " + childs.size() + " field in " + parent.getSimpleName() + " ... <<<");
//2.2 类继承于 ISyringe。
TypeSpec.Builder helper = TypeSpec.classBuilder(fileName)
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(type_ISyringe))
.addModifiers(PUBLIC);

//2.3 类中包含一个类型为 SerializationService,名称为 serializationService 的成员变量。
FieldSpec jsonServiceField = FieldSpec.builder(TypeName.get(type_JsonService.asType()), "serializationService", Modifier.PRIVATE).build();
helper.addField(jsonServiceField);

//2.4 对 Object 类型的形参进行强制转型。
injectMethodBuilder.addStatement("serializationService = $T.getInstance().navigation($T.class)", ARouterClass, ClassName.get(type_JsonService));
injectMethodBuilder.addStatement("$T substitute = ($T)target", ClassName.get(parent), ClassName.get(parent));

//2.5 开始对成员变量遍历进行赋值。
for (Element element : childs) {
Autowired fieldConfig = element.getAnnotation(Autowired.class);
String fieldName = element.getSimpleName().toString();
//2.5.1 如果是 IProvider 的子类,那么需要获取服务。
if (types.isSubtype(element.asType(), iProvider)) {
//没有指定名称,通过类型来获取。
if ("".equals(fieldConfig.name())) {

// Getter
injectMethodBuilder.addStatement(
"substitute." + fieldName + " = $T.getInstance().navigation($T.class)",
ARouterClass,
ClassName.get(element.asType())
);
//指定了名称,通过名称来获取。
} else {
injectMethodBuilder.addStatement(
"substitute." + fieldName + " = ($T)$T.getInstance().build($S).navigation();",
ClassName.get(element.asType()),
ARouterClass,
fieldConfig.name()
);
}

//异常情况处理。
if (fieldConfig.required()) {
injectMethodBuilder.beginControlFlow("if (substitute." + fieldName + " == null)");
injectMethodBuilder.addStatement(
"throw new RuntimeException(\"The field '" + fieldName + "' is null, in class '\" + $T.class.getName() + \"!\")", ClassName.get(parent));
injectMethodBuilder.endControlFlow();
}
//2.5.2 普通的成员变量。
} else {
String originalValue = "substitute." + fieldName;
String statement = "substitute." + fieldName + " = substitute.";
boolean isActivity = false;
//对 Activity 和 Fragment 进行不同的处理,分别使用 getIntent 和 getArguments 来获取参数。
if (types.isSubtype(parent.asType(), activityTm)) { // Activity, then use getIntent()
isActivity = true;
statement += "getIntent().";
} else if (types.isSubtype(parent.asType(), fragmentTm) || types.isSubtype(parent.asType(), fragmentTmV4)) { // Fragment, then use getArguments()
statement += "getArguments().";
} else {
throw new IllegalAccessException("The field [" + fieldName + "] need autowired from intent, its parent must be activity or fragment!");
}

statement = buildStatement(originalValue, statement, typeUtils.typeExchange(element), isActivity);
//需要通过序列化进行赋值的对象。
if (statement.startsWith("serializationService.")) { // Not mortals
injectMethodBuilder.beginControlFlow("if (null != serializationService)");
injectMethodBuilder.addStatement(
"substitute." + fieldName + " = " + statement,
(StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name()),
ClassName.get(element.asType())
);
injectMethodBuilder.nextControlFlow("else");
injectMethodBuilder.addStatement(
"$T.e(\"" + Consts.TAG + "\", \"You want automatic inject the field '" + fieldName + "' in class '$T' , then you should implement 'SerializationService' to support object auto inject!\")", AndroidLog, ClassName.get(parent));
injectMethodBuilder.endControlFlow();
//普通赋值的对象。
} else {
injectMethodBuilder.addStatement(statement, StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name());
}

//异常情况。
if (fieldConfig.required() && !element.asType().getKind().isPrimitive()) { // Primitive wont be check.
injectMethodBuilder.beginControlFlow("if (null == substitute." + fieldName + ")");
injectMethodBuilder.addStatement(
"$T.e(\"" + Consts.TAG + "\", \"The field '" + fieldName + "' is null, in class '\" + $T.class.getName() + \"!\")", AndroidLog, ClassName.get(parent));
injectMethodBuilder.endControlFlow();
}
}
}

helper.addMethod(injectMethodBuilder.build());

//2.6 写入文件。
JavaFile.builder(packageName, helper.build()).build().writeTo(mFiler);

logger.info(">>> " + parent.getSimpleName() + " has been processed, " + fileName + " has been generated. <<<");
}

logger.info(">>> Autowired processor stop. <<<");
}
}

/**
* 根据成员变量的类型进行区分。
* @param originalValue
* @param statement
* @param type
* @param isActivity
* @return
*/
private String buildStatement(String originalValue, String statement, int type, boolean isActivity) {
if (type == TypeKind.BOOLEAN.ordinal()) {
statement += (isActivity ? ("getBooleanExtra($S, " + originalValue + ")") : ("getBoolean($S)"));
} else if (type == TypeKind.BYTE.ordinal()) {
statement += (isActivity ? ("getByteExtra($S, " + originalValue + "") : ("getByte($S)"));
} else if (type == TypeKind.SHORT.ordinal()) {
statement += (isActivity ? ("getShortExtra($S, " + originalValue + ")") : ("getShort($S)"));
} else if (type == TypeKind.INT.ordinal()) {
statement += (isActivity ? ("getIntExtra($S, " + originalValue + ")") : ("getInt($S)"));
} else if (type == TypeKind.LONG.ordinal()) {
statement += (isActivity ? ("getLongExtra($S, " + originalValue + ")") : ("getLong($S)"));
}else if(type == TypeKind.CHAR.ordinal()){
statement += (isActivity ? ("getCharExtra($S, " + originalValue + ")") : ("getChar($S)"));
} else if (type == TypeKind.FLOAT.ordinal()) {
statement += (isActivity ? ("getFloatExtra($S, " + originalValue + ")") : ("getFloat($S)"));
} else if (type == TypeKind.DOUBLE.ordinal()) {
statement += (isActivity ? ("getDoubleExtra($S, " + originalValue + ")") : ("getDouble($S)"));
} else if (type == TypeKind.STRING.ordinal()) {
statement += (isActivity ? ("getStringExtra($S)") : ("getString($S)"));
} else if (type == TypeKind.PARCELABLE.ordinal()) {
statement += (isActivity ? ("getParcelableExtra($S)") : ("getParcelable($S)"));
} else if (type == TypeKind.OBJECT.ordinal()) {
statement = "serializationService.parseObject(substitute." + (isActivity ? "getIntent()." : "getArguments().") + (isActivity ? "getStringExtra($S)" : "getString($S)") + ", new com.alibaba.android.arouter.facade.model.TypeWrapper<$T>(){}.getType())";
}

return statement;
}

/**
* 进行分类处理。
* @param elements
* @throws IllegalAccessException
*/
private void categories(Set<? extends Element> elements) throws IllegalAccessException {
if (CollectionUtils.isNotEmpty(elements)) {
for (Element element : elements) {
TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
//不允许声明为 private。
if (element.getModifiers().contains(Modifier.PRIVATE)) {
throw new IllegalAccessException("The inject fields CAN NOT BE 'private'!!! please check field ["
+ element.getSimpleName() + "] in class [" + enclosingElement.getQualifiedName() + "]");
}

if (parentAndChild.containsKey(enclosingElement)) {
parentAndChild.get(enclosingElement).add(element);
} else {
List<Element> childs = new ArrayList<>();
childs.add(element);
parentAndChild.put(enclosingElement, childs);
}
}

logger.info("categories finished.");
}
}
}
ARouter.getInstance().inject(this);

最终创建的文件,其命名规则为 要注入的 Activity/Fragment + $$ARouter$$Autowired,以module-other的InjectActivity为例,最终生成的文件为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class InjectActivity$$ARouter$$Autowired implements ISyringe {
private SerializationService serializationService;

@Override
public void inject(Object target) {
serializationService = ARouter.getInstance().navigation(SerializationService.class);
InjectActivity substitute = (InjectActivity)target;
substitute.age = substitute.getIntent().getIntExtra("inject_age", substitute.age);
if (null != serializationService) {
substitute.bean = serializationService.parseObject(substitute.getIntent().getStringExtra("inject_object"), new com.alibaba.android.arouter.facade.model.TypeWrapper<SerialBean>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'bean' in class 'InjectActivity' , then you should implement 'SerializationService' to support object auto inject!");
}
}
}

当我们调用下面的方法时,就会通过反射创建该类的一个对象,然后调用它的inject方法,依次对各成员变量进行赋值。

1
ARouter.getInstance().inject(this);

总结

以上就是对于Arouter的编译时SDK的分析,这篇文章理解起来可能比较难,因为要求对编译期注解的处理有一定的了解。

通过分析源码,我们学习到了如何在编译期处理注解,并了解到了Arouter分组加载,拦截器以及依赖注入在编译期处理的原理,了解了这些,是我们之后学习Arouter的运行时SDK的基础,也可以借此机会学习它的思想,以后我们有遇到需要在编译期做一些事情的时候,可以拿出来参考。

您的支持是我原创的动力