
Android_Banner.jpg
简介
- AutowiredProcessor注解处理器是用来处理ARouter中Autowired注解,在process方法中编写处理逻辑
- 通常我们使用@Autowired注解来作用于目标类中的代接受数据的变量
- 我们看下生成的类文件,如图所示

WX20200713-180404@2x.png
源码分析
看下AutowiredProcessor
/处理@Autowired注解处理器
@SupportedAnnotationTypes({ANNOTATION_TYPE_AUTOWIRED})
//继承BaseProcessor
public class AutowiredProcessor extends BaseProcessor {}
AutowiredProcessor # process()
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
if (CollectionUtils.isNotEmpty(set)) {
try {
logger.info(">>> Found autowired field, start... <<<");
// -----> 分析1
categories(roundEnvironment.getElementsAnnotatedWith(Autowired.class));
// -------> 分析2
generateHelper();
} catch (Exception e) {
logger.error(e);
}
return true;
}
return false;
}
分析1:AutowiredProcessor # categories()
private void categories(Set<? extends Element> elements) throws IllegalAccessException {
if (CollectionUtils.isNotEmpty(elements)) {
// 使用@Autowired注解的类元素集合 elements
for (Element element : elements) {
//转换成类对应的Element -----> TypeElement
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() + "]");
}
// 当前类对应的typeElement为key 是否存存在于缓存中
if (parentAndChild.containsKey(enclosingElement)) { // Has categries
//如果存在 就将当前的element(类中@Autowired注解作用的成员变量)存在集合中
parentAndChild.get(enclosingElement).add(element);
} else {
//不存在,创建一个集合 存储这个element
List<Element> childs = new ArrayList<>();
childs.add(element);
//同时存储在parentAndChild (Map中)
parentAndChild.put(enclosingElement, childs);
}
}
logger.info("categories finished.");
}
}
- 总结
- categories()方法是用来进行分类的,set集合中装载这被@Autowired注解修饰的成员,这些成员有分别属于的类,
- 在此方法中 以Map集中来存储 类与类中被@Autowired注解修饰的成员变量的映射关系,其中被@Autowired注解修饰成员存储在List集合中
AutowiredProcessor # generateHelper()
private void generateHelper() throws IOException, IllegalAccessException {
TypeElement type_ISyringe = elementUtils.getTypeElement(ISYRINGE);
TypeElement type_JsonService = elementUtils.getTypeElement(JSON_SERVICE);
TypeMirror iProvider = elementUtils.getTypeElement(Consts.IPROVIDER).asType();
TypeMirror activityTm = elementUtils.getTypeElement(Consts.ACTIVITY).asType();
TypeMirror fragmentTm = elementUtils.getTypeElement(Consts.FRAGMENT).asType();
TypeMirror fragmentTmV4 = elementUtils.getTypeElement(Consts.FRAGMENT_V4).asType();
// Build input param name.
//构建方法的参数名称
ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build();
if (MapUtils.isNotEmpty(parentAndChild)) {
for (Map.Entry<TypeElement, List<Element>> entry : parentAndChild.entrySet()) {
// Build method : 'inject'
//构建inject方法
/**
* public void inject(Object target){}
*/
MethodSpec.Builder injectMethodBuilder = MethodSpec.methodBuilder(METHOD_INJECT)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(objectParamSpec);
//类
TypeElement parent = entry.getKey();
// 类中被@Autowired注解作用的成员集合
List<Element> childs = entry.getValue();
//类名
String qualifiedName = parent.getQualifiedName().toString();
String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
//构建生成文件的类名 类名$$ARouter$$Autowired
String fileName = parent.getSimpleName() + NAME_OF_AUTOWIRED;
logger.info(">>> Start process " + childs.size() + " field in " + parent.getSimpleName() + " ... <<<");
//构建类
/**
* public class className$$ARouter$$Autowired implements ISyringe{}
*/
TypeSpec.Builder helper = TypeSpec.classBuilder(fileName)
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(type_ISyringe))
.addModifiers(PUBLIC);
/**
* 序列化
*/
FieldSpec jsonServiceField = FieldSpec.builder(TypeName.get(type_JsonService.asType()), "serializationService", Modifier.PRIVATE).build();
helper.addField(jsonServiceField);
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));
// Generate method body, start inject.
/**
* 遍历集合,拿到该类中被@Autowired注解修饰的成员 element
*/
for (Element element : childs) {
Autowired fieldConfig = element.getAnnotation(Autowired.class);
String fieldName = element.getSimpleName().toString();
if (types.isSubtype(element.asType(), iProvider)) {// It's provider
//当成员中存在是Provider类型的 通过IoC ByType的方式 获取到它的实例
if ("".equals(fieldConfig.name())) { // User has not set service path, then use byType.
// Getter
injectMethodBuilder.addStatement(
"substitute." + fieldName + " = $T.getInstance().navigation($T.class)",
ARouterClass,
ClassName.get(element.asType())
);
} else { // use byName
// Getter
injectMethodBuilder.addStatement(
"substitute." + fieldName + " = ($T)$T.getInstance().build($S).navigation()",
ClassName.get(element.asType()),
ARouterClass,
fieldConfig.name()
);
}
// Validater
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();
}
} else { // It's normal intent value
String originalValue = "substitute." + fieldName;
String statement = "substitute." + fieldName + " = " + buildCastCode(element) + "substitute.";
boolean isActivity = false;
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!");
}
// 为成员赋值,通过从Intent中拿到对应的值,直接赋值给成员变量
statement = buildStatement(originalValue, statement, typeUtils.typeExchange(element), isActivity);
// 从json中解析出对应的对象
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())
);
//当没有找到实现SerializationService接口的的实现类的时候,会打印一个错误的信息log
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());
}
// Validator
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());
// Generate autowire helper
//生成对应的文件类 (className$$ARouter$$Autowired)
JavaFile.builder(packageName, helper.build()).build().writeTo(mFiler);
logger.info(">>> " + parent.getSimpleName() + " has been processed, " + fileName + " has been generated. <<<");
}
logger.info(">>> Autowired processor stop. <<<");
}
}
- 总结
- generateHelper()方法中,用来生成文件类的,包括类,方法以及方法的参数和方法体的逻辑
- 生成的文件类与parentAndChild的map集合形成对应,类中的方法体主要用来进行赋值的操作,包括基本数据类型的变量复制以及对象的赋值
- 在方法体中是通过类的实例.变量名的形式 进行赋值的,所以被@Autowired注解修饰的变量不能是private。
网友评论