什么是Arouter
Arouter是阿里开源的一款Android组件化的路由框架。它可以实现一个项目中模块间解耦,实现模块在不依赖其他模块的情况下也可以与其他模块进行通信。
Arouter的使用不在此文章做接收,有兴趣到Arouter的github上查看其使用。
Arouter既然是路由框架,那么就少不了路由表,导航、服务等都依赖路由表,而路由表的生成是依赖注解及编译时注解处理器,在编译期间,路由注解器会解析路由注解信息,并按照规则、模板自动生成路由、路由表等java文件。
Android 源码编译流程
注解处理器是在编译期解析源码中的注解信息,在根据规则、模板自动生成相应的java文件,那么注解处理器是在编译期的哪个阶段执行呢?
下图是Android Gradle源码编译的大概流程:
Gradle源码编译是会调用javac的编译程序,接着调用程序中的注解器执行,执行注解器任务发生在源码真正编译之前。
Arouter注解
Arouter目前提供的注解有以下三种:(其中Param被抛弃,推荐使用Autowried替换)
@Route
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Route {
/**
* Path of route
*/
String path();
/**
* Used to merger routes, the group name MUST BE USE THE COMMON WORDS !!!
*/
String group() default "";
/**
* Name of route, used to generate javadoc.
*/
String name() default "";
/**
* Extra data, can be set by user.
* Ps. U should use the integer num sign the switch, by bits. 10001010101010
*/
int extras() default Integer.MIN_VALUE;
/**
* The priority of route.
*/
int priority() default -1;
}
@Route的作用范围限定在类、接口、枚举及注解,生命周期为CLASS(只保留到编译器class文件中,jvm运行时被丢弃),参数有:
- group 路由所属的组别名称,如果不设置,那么会使用path中第一段//之间的字符串作为组别名称
- path 路由路径,必须以/开头
- name 路由名称,用于生成javadoc文档
- extras 路由父级信息,int类型,用途是int由32位组成,每一位代表一种状态,可以使用这个特性给予路由一些特殊的标志,如是否需要登录、安全校验等。
- priority 路由优先级
@Autowired
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.CLASS)
public @interface Autowired {
// Mark param's name or service name.
String name() default "";
// If required, app will be crash when value is null.
// Primitive type wont be check!
boolean required() default false;
// Description of the field
String desc() default "";
}
@Autowrited的作用范围是字段,生命周期为CLASS(只保留到编译器class文件中,jvm运行时被丢弃),参数有:
- name 标记属性的名称或者服务名称
- required 表示属性是否不能为空,默认为false
- desc 属性的描述信息
@Interceptor
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Interceptor {
/**
* The priority of interceptor, ARouter will be excute them follow the priority.
*/
int priority();
/**
* The name of interceptor, may be used to generate javadoc.
*/
String name() default "Default";
}
@Interceptor 的作用范围是类、接口、枚举及注解,生命周期为CLASS(只保留到编译器class文件中,jvm运行时被丢弃),参数有:
- priority 拦截器的优先级
- name 拦截器的名称
抽象注解处理器AbstractProcessor
注解器抽象类是AbstractProcessor,一般自定义注解器都需要继承并实现其抽象方法,主要方法有:
- getSupportedOptions:返回gradle 配置信息options中支持的key,比如Arouter模块gradle的option定义的模块名称:
android {
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
}
}
- getSupportedSourceVersion: 返回配置的源码版本,即JDK的版本
- init:注解处理器初始化函数
- process:注解处理器执行主体
注解器函数执行的流程是:构造方法——》init方法——》process方法
注解处理器中一些主要的类:
Element
Element是一个接口,它只在编译期存在和Type是有区别的,Element表示程序的一个元素,如:package、class、interface、method、成员变量、函数参数、泛型类型等。它可以提供当前元素的类型信息,如:类型名称、字段名称、包等。
Element常见的子类有:
- ExecutableElement:表示类或接口中的方法、构造函数construt、实例初始化函数init、类初始化函数cinit.
- PackageElement :表示包程序元素,它提供对包及其成员的访问。
- TypeElement:表示类、接口元素,它提供对类/接口的类型和方法信息的访问。注意枚举属于类类型,而注解属于接口类型。
- TypeParameterElement:表示类、接口、方法、构造函数的泛型类型,如泛型类型T
- VariableElement:表示字段、枚举常量、方法/构造函数的参数、本地变量、资源变量、异常参数
Element常见的函数有:
- asType:返回TypeMirror,TypeMirror是元素的类型信息,包括包名、类/方法/参数的名称或者类型等。TypeMirror的子类有:ArrayType、DeclaredType、ErrorType、ExecutableType、NoType、NullType、PrimitiveType、ReferenceType、TypeVariable、WildcardType,通过getKind可以获取类型。
- equal Element只能用equal方法进行比较
- getAnnotation(Class annotationType): 获取修饰此元素的指定注解类型的注解对象
- getAnnotationMirrors: 获取元素上的注解类型
- getEnclosedElements: 获取该元素上的直接子元素,类似一个类中有VariableElement
- getEnclosingElement: 获取该元素的父元素,如果是PackageElement则返回null,如果是TypeElement返回PackageElement,如果是TypeParameterElement则返回泛型Element,如果是成员函数或者成员变量则返回TypeElement.....
- getKind: 返回值为ElementKind,通过ElementKind可以知道是那种Element,具体就是Element的那些子类型。
- getSimpleName: 获取元素名称,不带包名,如果是变量返回的就是变量名,如果TypeElement返回的就是类名,如 String sex 获取age的getSimpleName返回的就是sex
- getQualifiedName: 获取类的全限定名,Element没有这个方法,但它的子类有,如TypeElement,得到的就是类的全限定名(包括包名)
ProcessingEnvironment
注解器处理器中编译器环境信息,可以提供文件生成器、类型处理工具类、元素处理工具类、日志打印等
Filer
注解处理器文件生成器,Arouter使用文件生成器配合使用squareup的javapoet库生成java源码文件
Types
类型处理工具类
Elements
元素处理工具类
Messager
日志工具类
Arouter注解处理器
Arouter注解处理器有:RouteProcessor、AutowiredProcessor、InterceptorProcessor,它们都继承与BaseProcessor,而BaseProcessor继承于AbstractProcessor。
BaseProcessor
public abstract class BaseProcessor extends AbstractProcessor {
Filer mFiler;
Logger logger;
Types types;
Elements elementUtils;
TypeUtils typeUtils;
// Module name, maybe its 'app' or others
String moduleName = null;
// If need generate router doc
boolean generateDoc;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
//从编译环境中获取文件生成器
mFiler = processingEnv.getFiler();
//从编译环境中获取类型处理工具类,主要是的对TypeMirror的操作
types = processingEnv.getTypeUtils();
//从编译环境中获取元素处理工具类
elementUtils = processingEnv.getElementUtils();
//将类型处理工具类与元素处理工具类进行包装,作为arouter注解器的类型处理工具类
typeUtils = new TypeUtils(types, elementUtils);
//将编译环境中获取的日志工具类包装为arouter注解器的日志工具类
logger = new Logger(processingEnv.getMessager());
// Attempt to get user configuration [moduleName]
/**
* 这里就是从每个模块的build.gradle的annotationProcessorOptions配置中取值模块名称
* 需要使用组件化的都需要配置改options,key对应的值就是模块名称
* 模块名称作为路由rootMap中的key,每个模块都对应生成一个root
*/
Map options = processingEnv.getOptions();
if (MapUtils.isNotEmpty(options)) {
moduleName = options.get(KEY_MODULE_NAME);
generateDoc = VALUE_ENABLE.equals(options.get(KEY_GENERATE_DOC_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(NO_MODULE_NAME_TIPS);
throw new RuntimeException("ARouter::Compiler >>> No module name, for more information, look at gradle log.");
}
}
@Override
public SourceVersion getSupportedSourceVersion() {
//配置源码版本,即JDK的版本
return SourceVersion.latestSupported();
}
@Override
public Set getSupportedOptions() {
//配置build.gradle中annotationProcessorOptions中optios的可以
//KEY_MODULE_NAME是一个字符串"AROUTER_MODULE_NAME"
return new HashSet() {{
this.add(KEY_MODULE_NAME);
this.add(KEY_GENERATE_DOC_NAME);
}};
}
}
RouteProcessor
RouteProcessor是生成一个模块的路由表的注解处理器,模块的路由表包括:路由组表、每个路由组组内路由表。
@AutoService(Processor.class)
@SupportedAnnotationTypes({ANNOTATION_TYPE_ROUTE, ANNOTATION_TYPE_AUTOWIRED})
public class RouteProcessor extends BaseProcessor {
//组内路由组表,key是组名称,value是路由组内的路由RouteMeta集合
private Map> groupMap = new HashMap<>(); // ModuleName and routeMeta.
//路由组表,key是组名称,value是路由组类RouteGroup类名
private Map rootMap = new TreeMap<>(); // Map of root metas, used for generate class file in order.
//Provider的类型信息
private TypeMirror iProvider = null;
//文档写工具类
private Writer docWriter; // Writer used for write doc
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
//初始化注解处理器
if (generateDoc) {
//如果要生成文档
try {
//使用文件生成器创建文档,打开文档并获取读写器
docWriter = mFiler.createResource(
StandardLocation.SOURCE_OUTPUT,
PACKAGE_OF_GENERATE_DOCS,
"arouter-map-of-" + moduleName + ".json"
).openWriter();
} catch (IOException e) {
logger.error("Create doc writer failed, because " + e.getMessage());
}
}
//获取模板中IProvider的类型信息对象
iProvider = elementUtils.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... <<<");
//调用parseRoutes方法对路由元素进行解析
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)) {
// prepare the type an so on.
logger.info(">>> Found routes, size is " + routeElements.size() + " <<<");
//清空路由组表
rootMap.clear();
//获取android.app.Activity的类型信息对象
TypeMirror type_Activity = elementUtils.getTypeElement(ACTIVITY).asType();
//获取android.app.Service的类型信息对象
TypeMirror type_Service = elementUtils.getTypeElement(SERVICE).asType();
//获取android.app.Fragment的类型信息对象
TypeMirror fragmentTm = elementUtils.getTypeElement(FRAGMENT).asType();
//获取android.support.v4.app.Fragment的类型信息对象
TypeMirror fragmentTmV4 = elementUtils.getTypeElement(Consts.FRAGMENT_V4).asType();
// Interface of ARouter
//获取IRouteGroup的类型元素对象
TypeElement type_IRouteGroup = elementUtils.getTypeElement(IROUTE_GROUP);
//获取IProviderGroup的类型元素对象
TypeElement type_IProviderGroup = elementUtils.getTypeElement(IPROVIDER_GROUP);
//获取RouteMeta的类名对象,用于替换$T.build:javapoet生成java文件的组成部分
ClassName routeMetaCn = ClassName.get(RouteMeta.class);
//获取RouteType的类名对象,用于替换RouteMeta.build($T.ACTIVITY):javapoet生成java文件的组成部分
ClassName routeTypeCn = ClassName.get(RouteType.class);
/*
1、创建生成RouteRoot、RouteGroup类中loadInto方法的参数类型
Build input type, format as :
```Map>```
*/
//javapoet生成java文件的组成部分
//生成RouteRoot文件的loadInto方法的参数类型对象,类型为Map>
ParameterizedTypeName inputMapTypeOfRoot = ParameterizedTypeName.get(
ClassName.get(Map.class), //参数类型
ClassName.get(String.class), //Map的key
ParameterizedTypeName.get( //Map的value,它是泛型又是参数类型对象
ClassName.get(Class.class),
WildcardTypeName.subtypeOf(ClassName.get(type_IRouteGroup))
)
);
/*
```Map```
*/
//javapoet生成java文件的组成部分
//生成RouteGroup类文件的loadInto方法的参数类型对象,类型为Map
ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(String.class),
ClassName.get(RouteMeta.class)
);
/*
2、定义RouteRoot、RouteGroup、Provider等类的loadInto方法的参数对象
Build input param name.
*/
//javapoet生成java文件的组成部分
//生成root文件中loadInto方法的参数:类型为Map>,参数名称为routes
ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, "routes").build();
//生成group文件中loadInto方法的参数:类型为Map,参数名称为atlas
ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "atlas").build();
//生成provider文件中loadInto方法的参数:类型为Map,参数名称为providers
ParameterSpec providerParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "providers").build(); // Ps. its param type same as groupParamSpec!
/*
3、生成对应的RouteRoot类方法loadInto的Builder,在后面会使用到
Build method : 'loadInto'
*/
//生成对应的Root文件中的loadInto方法Builder对象
MethodSpec.Builder loadIntoMethodOfRootBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO) //方法名为:loadInto
.addAnnotation(Override.class) //重新
.addModifiers(PUBLIC) //方法为public
.addParameter(rootParamSpec); //方法参数Map> routes
// Follow a sequence, find out metas of group first, generate java file, then statistics them as root.
//4、遍历所有路由元素
//将路由元素进行分组,每个group有多个路由,组成一个路由分组表groupMap,key是分组名,value是Set集合的组内的路由列表
//先根据路由元素中的信息构建为一个RouteMeta(路由元信息),对其分组,再将组统计为root
for (Element element : routeElements) {
//获取路由元素的类型信息
TypeMirror tm = element.asType();
//获取路由元素中的@Route注解信息
Route route = element.getAnnotation(Route.class);
//声明路由元信息
RouteMeta routeMeta;
// Activity or Fragment
if (types.isSubtype(tm, type_Activity) || types.isSubtype(tm, fragmentTm) || types.isSubtype(tm, fragmentTmV4)) {
//如果路由元素是Activity或者fragment或者support v4的fragment的子类
// Get all fields annotation by @Autowired
//获取该元素中所有被@Autowrited注解的字段
//被@Autowrited注解的字段的类型
Map paramsType = new HashMap<>();
//被@Autowrited注解的字段的注入配置
Map injectConfig = new HashMap<>();
//收集@Autowrited注解并生成注入配置信息
injectParamCollector(element, paramsType, injectConfig);
if (types.isSubtype(tm, type_Activity)) {
// Activity
//如果路由元素是Activity
logger.info(">>> Found activity route: " + tm.toString() + " <<<");
/**
* 构建Activity类型的路由元信息
* route: 路由注解信息,通过它可以得到路由group、path、name等信息
* element:路由注解所修饰的元素,这里是Activity的子类
* RouteType:枚举类型,表示当前路由为Activity类型
* paramsType:Activity中@Autowrited修饰的元素的类型列表
*/
routeMeta = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType);
} else {
//如果路由元素是 Fragment
/**
* 构建Fragment类型的路由元信息
* route: 路由注解信息,通过它可以得到路由group、path、name等信息
* element:路由注解所修饰的元素,这里是Fragment的子类
* RouteType:枚举类型,表示当前路由为Fragment类型
* paramsType:Fragment中@Autowrited修饰的元素的类型列表
*/
logger.info(">>> Found fragment route: " + tm.toString() + " <<<");
routeMeta = new RouteMeta(route, element, RouteType.parse(FRAGMENT), paramsType);
}
//设置路由元需要注入的配置信息,及@Autowrited的配置信息
routeMeta.setInjectConfig(injectConfig);
} else if (types.isSubtype(tm, iProvider)) { // IProvider
//如果路由元素是Arouter的IProvider的子类
logger.info(">>> Found provider route: " + tm.toString() + " <<<");
/**
* 构建Provider类型的路由元信息
* route: 路由注解信息,通过它可以得到路由group、path、name等信息
* element:路由注解所修饰的元素,这里是IProvider的子类
* RouteType:枚举类型,表示当前路由为Provider类型
* paramsType:空,即不支持@Autowrited依赖注入
*/
routeMeta = new RouteMeta(route, element, RouteType.PROVIDER, null);
} else if (types.isSubtype(tm, type_Service)) { // Service
//如果路由元素是Service
logger.info(">>> Found service route: " + tm.toString() + " <<<");
/**
* 构建Service类型的路由元信息
* route: 路由注解信息,通过它可以得到路由group、path、name等信息
* element:路由注解所修饰的元素,这里是Service的子类
* RouteType:枚举类型,表示当前路由为Service类型
* paramsType:空,即不支持@Autowrited依赖注入
*/
routeMeta = new RouteMeta(route, element, RouteType.parse(SERVICE), null);
} else {
//如果路由元素不是上述类型,那么抛出异常,即路由元素仅支持Activity、Fragment、Service、Arouter的Provider
throw new RuntimeException("The @Route is marked on unsupported class, look at [" + tm.toString() + "].");
}
//对路由进行分组并进行组内排序
//将同组的路由保存在一个Set集合中,并且使用Group名作为key保存到groupMap中
categories(routeMeta);
}
//构建Provider的loadInto方法Builder对象
MethodSpec.Builder loadIntoMethodOfProviderBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO) //方法名为loadInto
.addAnnotation(Override.class)//重写
.addModifiers(PUBLIC) //public
.addParameter(providerParamSpec); //provider的loadInto方法的参数是:Map providers
//路由文档Map
Map> docSource = new HashMap<>();
// Start generate java source, structure is divided into upper and lower levels, used for demand initialization.
for (Map.Entry> entry : groupMap.entrySet()) {
//遍历路由组
//获取路由组名称
String groupName = entry.getKey();
//构建路由组RouteGroup的loadInto方法的Builder
MethodSpec.Builder loadIntoMethodOfGroupBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(groupParamSpec);
//路由文档列表
List routeDocList = new ArrayList<>();
// Build group method body
Set groupData = entry.getValue();
for (RouteMeta routeMeta : groupData) {
//遍历组内路由列表
//将路由元信息转为路由文档信息
RouteDoc routeDoc = extractDocInfo(routeMeta);
//获取路由真实类名对象
ClassName className = ClassName.get((TypeElement) routeMeta.getRawType());
switch (routeMeta.getType()) {
case PROVIDER: // Need cache provider's super class
//如果路由类型是Provider
//获取Provider实现的接口类型列表包括其父类的
List extends TypeMirror> interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces();
for (TypeMirror tm : interfaces) {
//遍历接口列表
routeDoc.addPrototype(tm.toString());
/**
* 构建Provider类文件中方法loadInto的内容
* Provider文件其实类似Group文件,只不过provider中Map的key不是path而是实现了IProvider接口的类的全限定名
*/
if (types.isSameType(tm, iProvider)) { // Its implements iProvider interface himself.
// This interface extend the IProvider, so it can be used for mark provider
//如果接口tm就是IProvider
//生成Provider的loadInto方法内容
/**
* 方法内容为:
* providers.put(ProviderImpl.classname, RouteMeta.Build(RouteType.XXX, ProviderImpl.class, routePath, routeGroup, null, routePriority, routeExtra))
* 其中RouteMeta.build调用的是build(RouteType type, Class> destination, String path, String group, Map paramsType, int priority, int extra)
* 其实就是构建出Provider的路由元信息,用Provider的类权限定名做为key,Provider的路由元信息做为value,存储在providers的Map中
*/
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, //Iprovider的最终实现类
routeMeta.getPath(),
routeMeta.getGroup());
} else if (types.isSubtype(tm, iProvider)) {
// This interface extend the IProvider, so it can be used for mark provider
//如果接口是IProvider的子类
//生成Provider的loadInto方法内容
/**
* 方法内容为:
* providers.put(ProviderImpl.classname, RouteMeta.Build(RouteType.XXX, ProviderImpl.class, routePath, routeGroup, null, routePriority, routeExtra))
* 其中RouteMeta.build调用的是build(RouteType type, Class> destination, String path, String group, Map paramsType, int priority, int extra)
* 其实就是构建出Provider的路由元信息,用Provider的类权限定名做为key,Provider的路由元信息做为value,存储在providers的Map中
*/
loadIntoMethodOfProviderBuilder.addStatement(
"providers.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, null, " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))",
tm.toString(), // So stupid, will duplicate only save class name.
routeMetaCn,
routeTypeCn,
className, //Iprovider的最终实现类
routeMeta.getPath(),
routeMeta.getGroup());
}
}
break;
default:
break;
}
// Make map body for paramsType
/**
* 生成@Autowrited修饰的元素的类型map
*/
StringBuilder mapBodyBuilder = new StringBuilder();
//获取@Autowrited修饰的元素的类型map
Map paramsType = routeMeta.getParamsType();
//获取@Autowrited修饰的元素的注入配置信息
Map injectConfigs = routeMeta.getInjectConfig();
if (MapUtils.isNotEmpty(paramsType)) {
//如果存在@Autowrited修饰的元素
List paramList = new ArrayList<>();
for (Map.Entry types : paramsType.entrySet()) {
//遍历@Autowrited修饰的元素的类型
//将@Autowrited修饰的元素的类型转为字符串形式:put("typeKey", typeValue);字符串放入mapBodyBuilder中
mapBodyBuilder.append("put(\"").append(types.getKey()).append("\", ").append(types.getValue()).append("); ");
//生成路由文档的参数信息
RouteDoc.Param param = new RouteDoc.Param();
Autowired injectConfig = injectConfigs.get(types.getKey());
param.setKey(types.getKey());
param.setType(TypeKind.values()[types.getValue()].name().toLowerCase());
param.setDescription(injectConfig.desc());
param.setRequired(injectConfig.required());
paramList.add(param);
}
routeDoc.setParams(paramList);
}
//这里是路由中@Autowrited修饰的元素的类型map内容部分
String mapBody = mapBodyBuilder.toString();
/**
* 定义group文件的loadInto方法的内容:
* atlas.put(routePath, RouteMeta.build(RouteType.xxx, RouteImpl.class, routePath, routeGroup, autowritedmapBody, routePriority, routeExtra))
* 其实就是构建路由元对象RouteMeta,并放入路由组atlas中,atlas是一个Map,
* key 是路由路径,value是RouteMeta
*/
loadIntoMethodOfGroupBuilder.addStatement(
"atlas.put($S, $T.build($T." + routeMeta.getType() + ", $T.class, $S, $S, " + (StringUtils.isEmpty(mapBody) ? null : ("new java.util.HashMap(){{" + mapBodyBuilder.toString() + "}}")) + ", " + routeMeta.getPriority() + ", " + routeMeta.getExtra() + "))",
routeMeta.getPath(),
routeMetaCn,
routeTypeCn,
className,
routeMeta.getPath().toLowerCase(),
routeMeta.getGroup().toLowerCase());
routeDoc.setClassName(className.toString());
routeDocList.add(routeDoc);
}
// Generate groups
//路由组Group文件名:ARouter$$Group$$groupName
String groupFileName = NAME_OF_GROUP + groupName;
//使用javapoet集合文件生成器mFiler生成RouteGroup文件
JavaFile.builder(PACKAGE_OF_GENERATE_FILE, //包名
TypeSpec.classBuilder(groupFileName) //类名
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(type_IRouteGroup)) //实现IRouteGroup接口
.addModifiers(PUBLIC) //public
.addMethod(loadIntoMethodOfGroupBuilder.build()) //类的方法loadInto
.build()
).build().writeTo(mFiler);
logger.info(">>> Generated group: " + groupName + "<<<");
//将group放入模块路由组表Map中,key是组名,value是Group的类名字符串
rootMap.put(groupName, groupFileName);
docSource.put(groupName, routeDocList);
}
if (MapUtils.isNotEmpty(rootMap)) {
// Generate root meta by group name, it must be generated before root, then I can find out the class of group.
//如果路由组表不为空
for (Map.Entry entry : rootMap.entrySet()) {
//遍历路由组表
//生成模块根路由RouteRoot的loadInto方法的内容:
//routes.put(groupName, RouteGroup),routes是loadInto方法的参数Map> routes
loadIntoMethodOfRootBuilder.addStatement("routes.put($S, $T.class)", entry.getKey(), ClassName.get(PACKAGE_OF_GENERATE_FILE, entry.getValue()));
}
}
//输出Route文档
// Output route doc
if (generateDoc) {
docWriter.append(JSON.toJSONString(docSource, SerializerFeature.PrettyFormat));
docWriter.flush();
docWriter.close();
}
// Write provider into disk
//使用javapoet结合文件生成器mFiler生成Provider文件
//provider类文件名也是类名:ARouter$$Providers$$moduleName
String providerMapFileName = NAME_OF_PROVIDER + SEPARATOR + moduleName; //
JavaFile.builder(PACKAGE_OF_GENERATE_FILE, //provider包名
TypeSpec.classBuilder(providerMapFileName) //provider类名
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(type_IProviderGroup)) //provider实现的接口IProviderGroup
.addModifiers(PUBLIC)
.addMethod(loadIntoMethodOfProviderBuilder.build())
.build()
).build().writeTo(mFiler);
logger.info(">>> Generated provider map, name is " + providerMapFileName + " <<<");
// Write root meta into disk.
//使用javapoet结合文件生成器mFiler生成RouteRoot文件
//模块根路由类文件名也是类名:ARouter$$Root$$moduleName
String rootFileName = NAME_OF_ROOT + SEPARATOR + moduleName;
JavaFile.builder(PACKAGE_OF_GENERATE_FILE, //包名
TypeSpec.classBuilder(rootFileName) //类名
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(elementUtils.getTypeElement(ITROUTE_ROOT))) //RouteRoot实现的接口IRouteRoot
.addModifiers(PUBLIC)
.addMethod(loadIntoMethodOfRootBuilder.build()) //添加RouteRoot的方法loadInto
.build()
).build().writeTo(mFiler);
logger.info(">>> Generated root, name is " + rootFileName + " <<<");
}
}
/**
* Recursive inject config collector.
*
* @param element current element.
*/
private void injectParamCollector(Element element, Map paramsType, Map injectConfig) {
//收集@Route修饰的元素element下的所有@Autowrited的信息
for (Element field : element.getEnclosedElements()) {
//获取@Route修饰的元素element下的所有子元素,包括字段、方法
if (field.getKind().isField() && field.getAnnotation(Autowired.class) != null && !types.isSubtype(field.asType(), iProvider)) {
//如果子元素是字段且被@Autorited注解修饰,且字段不是provider子类
// It must be field, then it has annotation, but it not be provider.
//获取字段@Autorited注解对象
Autowired paramConfig = field.getAnnotation(Autowired.class);
//获取字段名或者别名
String injectName = StringUtils.isEmpty(paramConfig.name()) ? field.getSimpleName().toString() : paramConfig.name();
//获取字段类型,并存入类型表中
paramsType.put(injectName, typeUtils.typeExchange(field));
//注入名称和@Autorited注解对象放入依赖注入配置表中
injectConfig.put(injectName, paramConfig);
}
}
// if has parent?
//@Route修饰的元素element的父类类型信息
TypeMirror parent = ((TypeElement) element).getSuperclass();
if (parent instanceof DeclaredType) {
//父类类型信息是类或接口
//父类类型信息对象转为程序元素
Element parentElement = ((DeclaredType) parent).asElement();
if (parentElement instanceof TypeElement && !((TypeElement) parentElement).getQualifiedName().toString().startsWith("android")) {
//如果父类元素是类/接口,且父类元素不是android包下的类
//继续递归调用injectParamCollector收集@Autowrited注解信息
injectParamCollector(parentElement, paramsType, injectConfig);
}
}
}
/**
* Extra doc info from route meta
*
* @param routeMeta meta
* @return doc
*/
private RouteDoc extractDocInfo(RouteMeta routeMeta) {
//将路由元信息类RouteMeta转为路由文档类
RouteDoc routeDoc = new RouteDoc();
routeDoc.setGroup(routeMeta.getGroup());
routeDoc.setPath(routeMeta.getPath());
routeDoc.setDescription(routeMeta.getName());
routeDoc.setType(routeMeta.getType().name().toLowerCase());
routeDoc.setMark(routeMeta.getExtra());
return routeDoc;
}
/**
* Sort metas in group.
*
* @param routeMete metas.
*/
private void categories(RouteMeta routeMete) {
//对路由进行分组
if (routeVerify(routeMete)) {
//校验路由元信息,如果是合法的路由,则:
logger.info(">>> Start categories, group = " + routeMete.getGroup() + ", path = " + routeMete.getPath() + " <<<");
//根据路由组名从路由组表groupMap获取组内路由集合
Set routeMetas = groupMap.get(routeMete.getGroup());
if (CollectionUtils.isEmpty(routeMetas)) {
//如果组内路由集合为空
//新建一个组内路由集合
Set routeMetaSet = new TreeSet<>(new Comparator() {
@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加入新的路由组,key是路由组名,value是组内路由集合
groupMap.put(routeMete.getGroup(), routeMetaSet);
} else {
//如果组内路由集合不为空
//将路由加入组内路由集合
routeMetas.add(routeMete);
}
} else {
logger.warning(">>> Route meta verify error, group is " + routeMete.getGroup() + " <<<");
}
}
/**
* Verify the route meta
*
* @param meta raw meta
*/
private boolean routeVerify(RouteMeta meta) {
//校验路由元信息
//路由路径
String path = meta.getPath();
if (StringUtils.isEmpty(path) || !path.startsWith("/")) { // The path must be start with '/' and not empty!
//如果路由路径为空或者不是以/开头,则返回false,表示非法的路由
return false;
}
if (StringUtils.isEmpty(meta.getGroup())) { // Use default group(the first word in path)
//如果路由没有设置组名
//则使用路由路径path的第一度//中的内容作为路由组名
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;
}
}
根据上述对RouteProcessor源码解析,我们可以得出以下结论:
1、RouteProcessor注解处理器处理的是@Route注解
2、RouteProcessor会生成三类java文件,分别是:RouteRoot文件(每个模块一个,模块根路由表文件)、RouteGroup文件(每个模块存在多个分组,每个组对应一个RouteGroup文件)、Provider文件(每个模块一个,模块提供的服务表文件)
- RouteRoot: 模块根路由表文件,每个模块只有一个文件,实现IRouteRoot接口,维护模块根路由Map,key是模块名(即路由组名)、value是路由组RouteGroup实现的类
- RouteGroup:每组路由表文件,每组对应一个路由组文件,实现IRouteGroup接口,维护路由组Map, key是组名,value是有RouteMeta组成的路由Set集合
- Provider:模块提供的服务表文件,只有一个文件,实现IProvider接口,维护providerMap,key是provider真实实现类全限定名,value是表示provider类型的RouteMeta对象
3、RouteProcessor是围绕@route的注解,解析生成RouteRoot、RouteGroup、Provider这三种文件,其流程:
3.1、从编译环境RoundEnvironment中读取所有被@Route注解修饰的元素列表
3.2、生成路由表文件RouteRoot的方法loadIntod的参数及名称
3.3、生成路由组文件RouteGroup的方法loadInto的参数及名称
3.4、生成路由组文件Provider的方法loadInto的参数及名称
3.5、遍历@Route注解修饰的元素列表
3.5.1、根据注解信息生成路由元信息对象RouteMeta,同时收集activity、fragment中需要依赖注入@Autowrited的参数类型及配置信息
3.5.2、对RouteMeta进行分组,把RouteMeta放入对应的路由组表groupMap中,组名使用注解中的group,如果为空则使用path中第一段//作为组名
3.6、遍历分好组的路由组groupMap
3.6.1、对provider进行过滤,并生成provider文件的方法及方法参数及方法内容;
3.6.2、同时生成每个路由组对应的RouteGroup文件中的方法及参数及方法内容
3.6.3、生成每个路由组对应的RouteGroup文件
3.6.4、将模块中的路由组RouteGroup进行归档到根路由表routeMap中
3.7、遍历根路由表routeMap生成根路由文件的loadInto方法的方法内容
3.8、根据生成provider的loadInto方法、方法参数、参数名称、方法内容生成provider文件
3.9、根据生成根路由的loadInto方法、方法参数、参数名称、方法内容生成根路由文件RouteRoot
AutowiredProcessor
AutowiredProcessor注解处理器是用来生成依赖注入工具类,对被@Autowrited注解修饰的字段进行赋值,我们先分析其源码:
@AutoService(Processor.class)
@SupportedAnnotationTypes({ANNOTATION_TYPE_AUTOWIRED})
public class AutowiredProcessor extends BaseProcessor {
//autowrited关系表,key是包含@Autowrited的类类型,value是类中此类中被@Autowrited注解的元素列表
private Map> parentAndChild = new HashMap<>(); // Contain field need autowired and his super class.
//Arouter类名对象
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);
//初始化AutowiredProcessor注解处理器
logger.info(">>> AutowiredProcessor init. <<<");
}
@Override
public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
//执行AutowiredProcessor注解处理器的处理程序
if (CollectionUtils.isNotEmpty(set)) {
//如果程序存在类、接口等类类型,则:
try {
logger.info(">>> Found autowired field, start... <<<");
//从编译环境对象中读取所有被@Autowired注解修饰的元素,并进行分类解析
categories(roundEnvironment.getElementsAnnotatedWith(Autowired.class));
//生成Autowrited依赖注入工具类
generateHelper();
} catch (Exception e) {
logger.error(e);
}
return true;
}
return false;
}
private void generateHelper() throws IOException, IllegalAccessException {
//生成依赖注入工具类
//获取注射器ISyringe的类类型,是生成java类需要实现的接口类型
TypeElement type_ISyringe = elementUtils.getTypeElement(ISYRINGE);
//获取序列化服务SerializationService的类类型,它用于解析json字符串,是操作对象、列表、map等数据的处理类
TypeElement type_JsonService = elementUtils.getTypeElement(JSON_SERVICE);
//获取IProvider的类型信息对象
TypeMirror iProvider = elementUtils.getTypeElement(Consts.IPROVIDER).asType();
//获取android.app.Activity的类型信息对象
TypeMirror activityTm = elementUtils.getTypeElement(Consts.ACTIVITY).asType();
//获取android.app.Fragment的类型信息对象
TypeMirror fragmentTm = elementUtils.getTypeElement(Consts.FRAGMENT).asType();
//获取android.support.v4.app.Fragment的类型信息对象
TypeMirror fragmentTmV4 = elementUtils.getTypeElement(Consts.FRAGMENT_V4).asType();
// Build input param name.
//开始构建注入方法的原型:public void inject(Object target)
//定义注入方法inject的参数和名称:Object是参数类型,target是参数名称
ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build();
if (MapUtils.isNotEmpty(parentAndChild)) {
//如果autowrited关系表不为空
for (Map.Entry> entry : parentAndChild.entrySet()) {
//遍历autowrited关系表
// Build method : 'inject'
//创建注入方法inject的Builder,方法名称是inject,参数是前面创建的:参数类型为Object,参数名称为targe
MethodSpec.Builder injectMethodBuilder = MethodSpec.methodBuilder(METHOD_INJECT) //方法名
.addAnnotation(Override.class) //重写
.addModifiers(PUBLIC) //public
.addParameter(objectParamSpec); //方法参数及参数名称
//包含@Autowrited注解的元素,如Activity、fragment
TypeElement parent = entry.getKey();
//类中包含被@Autowrited注解的元素列表
List 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() + " ... <<<");
//生成要生成的类的Builder
TypeSpec.Builder helper = TypeSpec.classBuilder(fileName) //类名
.addJavadoc(WARNING_TIPS)
.addSuperinterface(ClassName.get(type_ISyringe)) //实现的注射器ISyringe接口
.addModifiers(PUBLIC); //public访问权限
//定义生成中中的字段:private SerializationService serializationService;
FieldSpec jsonServiceField = FieldSpec.builder(TypeName.get(type_JsonService.asType()), "serializationService", Modifier.PRIVATE).build();
helper.addField(jsonServiceField);
//添加类中注入方法inject的内容:serializationService = ARouter.getInstance().navigation(SerializationService.class)
injectMethodBuilder.addStatement("serializationService = $T.getInstance().navigation($T.class)", ARouterClass, ClassName.get(type_JsonService));
//添加类中注入方法inject的内容:xxxActivity/xxxFragment substitute = (xxxActivity/xxxFragment) target;
injectMethodBuilder.addStatement("$T substitute = ($T)target", ClassName.get(parent), ClassName.get(parent));
// Generate method body, start inject.
//生成注入方法inject的主体,并开始实现注入
for (Element element : childs) {
//遍历类中被@Autowrited注解的元素
//获取元素的注解信息对象
Autowired fieldConfig = element.getAnnotation(Autowired.class);
//获取元素的名称
String fieldName = element.getSimpleName().toString();
if (types.isSubtype(element.asType(), iProvider)) { // It's provider
//如果元素是Provider类型,则:
if ("".equals(fieldConfig.name())) { // User has not set service path, then use byType.
//该元素被@Autowrited修饰时,没有指定name,则:
// Getter
//添加类中注入方法inject的内容:substitute.fieldName = Arouter.getInstance().navigation(ProviderXXX.class);
injectMethodBuilder.addStatement(
"substitute." + fieldName + " = $T.getInstance().navigation($T.class)",
ARouterClass,
ClassName.get(element.asType())
);
} else { // use byName
// Getter
//添加类中注入方法inject的内容:substitute.fieldName = Arouter.getInstance().navigation(@Autowrited.name);
injectMethodBuilder.addStatement(
"substitute." + fieldName + " = ($T)$T.getInstance().build($S).navigation()",
ClassName.get(element.asType()),
ARouterClass,
fieldConfig.name()
);
}
// Validator
if (fieldConfig.required()) {
//如果@Autowrited修饰的元素不能为空,则在inject方法中加上为空则抛出异常:
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
//元素类型不是Provider,则代表是intent类型的值
//获取元素原始值语句
String originalValue = "substitute." + fieldName;
//生成注入赋值语句:substitute.fieldName = (ElementType) substitute.
// or 生成注入赋值语句:substitute.fieldName = substitute.
String statement = "substitute." + fieldName + " = " + buildCastCode(element) + "substitute.";
boolean isActivity = false;
if (types.isSubtype(parent.asType(), activityTm)) { // Activity, then use getIntent()
//该类是Activity的子类,则:
isActivity = true;
//继续构建注入赋值语句:substitute.fieldName = substitute.getIntent().
statement += "getIntent().";
} else if (types.isSubtype(parent.asType(), fragmentTm) || types.isSubtype(parent.asType(), fragmentTmV4)) { // Fragment, then use getArguments()
//该类是Fragment的子类,则:
//继续构建注入赋值语句:substitute.fieldName = substitute.getArguments().
statement += "getArguments().";
} else {
//如果@Autowrited修饰的不是Activity、Fragment则抛出异常
throw new IllegalAccessException("The field [" + fieldName + "] need autowired from intent, its parent must be activity or fragment!");
}
//继续构建注入赋值语句:substitute.fieldName = [(ElementType)]substitute.[getIntent() | getArguments()].getXXX[Extra](xxx,[originalValue ])
statement = buildStatement(originalValue, statement, typeUtils.typeExchange(element), isActivity, isKtClass(parent));
if (statement.startsWith("serializationService.")) { // Not mortals
//如果注入赋值语句是序列化serializationService语句,则:
//注入方法继续加语句: 如果序列化之后serializationService不为空,则继续完成序列化赋值语句
injectMethodBuilder.beginControlFlow("if (null != serializationService)");
injectMethodBuilder.addStatement(
"substitute." + fieldName + " = " + statement,
(StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name()),
ClassName.get(element.asType())
);
//如果序列化之后serializationService为空,则注入方法中加入日志打印语句
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.
//如果@Autowrited注解修饰的元素不允许为空,且不是基本类型,则:
//注入方法中加入语句:判断元素如果为空则抛出异常
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
//使用javapoet结合文件生成工具mFiler生成注入工具类
JavaFile.builder(packageName, helper.build()).build().writeTo(mFiler);
logger.info(">>> " + parent.getSimpleName() + " has been processed, " + fileName + " has been generated. <<<");
}
logger.info(">>> Autowired processor stop. <<<");
}
}
private boolean isKtClass(Element element) {
//判断是否是Kotlin类
for (AnnotationMirror annotationMirror : elementUtils.getAllAnnotationMirrors(element)) {
if (annotationMirror.getAnnotationType().toString().contains("kotlin")) {
return true;
}
}
return false;
}
private String buildCastCode(Element element) {
if (typeUtils.typeExchange(element) == TypeKind.SERIALIZABLE.ordinal()) {
//判断是否是序列化类型,如果是需要添加类型转换语句
return CodeBlock.builder().add("($T) ", ClassName.get(element.asType())).build().toString();
}
return "";
}
/**
* Build param inject statement
*/
private String buildStatement(String originalValue, String statement, int type, boolean isActivity, boolean isKt) {
//完成注入负责语句,其实就是生成activity.getIntent().getXXXExtra的赋值语句或者fragment.getArguments().getXXX
switch (TypeKind.values()[type]) {
case BOOLEAN:
statement += "getBoolean" + (isActivity ? "Extra" : "") + "($S, " + originalValue + ")";
break;
case BYTE:
statement += "getByte" + (isActivity ? "Extra" : "") + "($S, " + originalValue + ")";
break;
case SHORT:
statement += "getShort" + (isActivity ? "Extra" : "") + "($S, " + originalValue + ")";
break;
case INT:
statement += "getInt" + (isActivity ? "Extra" : "") + "($S, " + originalValue + ")";
break;
case LONG:
statement += "getLong" + (isActivity ? "Extra" : "") + "($S, " + originalValue + ")";
break;
case CHAR:
statement += "getChar" + (isActivity ? "Extra" : "") + "($S, " + originalValue + ")";
break;
case FLOAT:
statement += "getFloat" + (isActivity ? "Extra" : "") + "($S, " + originalValue + ")";
break;
case DOUBLE:
statement += "getDouble" + (isActivity ? "Extra" : "") + "($S, " + originalValue + ")";
break;
case STRING:
statement += (isActivity ? ("getExtras() == null ? " + originalValue + " : substitute.getIntent().getExtras().getString($S") : ("getString($S")) + ", " + originalValue + ")";
break;
case SERIALIZABLE:
statement += (isActivity ? ("getSerializableExtra($S)") : ("getSerializable($S)"));
break;
case PARCELABLE:
statement += (isActivity ? ("getParcelableExtra($S)") : ("getParcelable($S)"));
break;
case OBJECT:
statement = "serializationService.parseObject(substitute." + (isActivity ? "getIntent()." : "getArguments().") + (isActivity ? "getStringExtra($S)" : "getString($S)") + ", new " + TYPE_WRAPPER + "<$T>(){}.getType())";
break;
}
return statement;
}
/**
* Categories field, find his papa.
*
* @param elements Field need autowired
*/
private void categories(Set extends Element> elements) throws IllegalAccessException {
//对被@Autowrited注解修饰的元素进行分类
if (CollectionUtils.isNotEmpty(elements)) {
//如果存在被@Autowrited注解修饰的元素
for (Element element : elements) {
//遍历被@Autowrited注解修饰的元素列表
//从被@Autowrited注解修饰的元素element取其父类,如Activity、framgment等
TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
if (element.getModifiers().contains(Modifier.PRIVATE)) {
//如果@Autowrited注解修饰的元素是私有字段,则抛出异常
throw new IllegalAccessException("The inject fields CAN NOT BE 'private'!!! please check field ["
+ element.getSimpleName() + "] in class [" + enclosingElement.getQualifiedName() + "]");
}
if (parentAndChild.containsKey(enclosingElement)) { // Has categries
//如果autowrited关系表中已经存在此父类,则
//将被@Autowrited注解修饰的元素加入autowrited关系表
parentAndChild.get(enclosingElement).add(element);
} else {
//如果autowrited关系表中不存在此父类,则
//创建此父类中被@Autowrited注解修饰的元素列表
List childs = new ArrayList<>();
//将被@Autowrited注解修饰的元素加入列表中
childs.add(element);
//autowrited关系表加入类与@Autowrited修饰的元素列表
parentAndChild.put(enclosingElement, childs);
}
}
logger.info("categories finished.");
}
}
}
根据上述对@Autowrited源码分析,我们可以得出以下结论:
1、@Autowrited修饰Activity、android.app.Fragment、android.support.v4.app.Fragment中的字段
2、@Autowrited实现依赖注入的原理其实就是在编译时生成对应的一个工具类,Activity、Fragment调用inject方法时,其实就是调用该类对应工具类的inject方法,然后实现从getIntent或者getArguments获取对应的值赋值给字段
3、每个Activity、Fragment子类中需要使用@Autowrited进行依赖注入的,都会在编译期自动生成一个该类的一个辅助类,用于实现依赖注入
4、AutoProcessor注解处理器生成依赖注入辅助类的流程是:
4.1、从编译环境中读取所有被@Autowrited注解修饰的元素
4.2、对被@Autowrited注解修饰的元素进行归来,生成autowrited关系表,key是使用了@Autowrited注解的真实类的类型元素对象,value是该类中被被@Autowrited注解修饰的元素列表
4.3、获取ISyringe的类型元素对象,后续生成的辅助类需要实现的接口
4.4、获取序列化服务SerializationService的类型元素,它用于解析json字符串,是操作对象、列表、map等数据的处理类
4.5、获取IProvider、Activity、Fragment的类型信息对象
4.6、创建辅助类中inject方法的参数及名称:Object target
4.7、遍历autowrited关系表:
4.7.1、生成注入方法inject并创建辅助类helper,类名为:xxxActivity/FragmentAutowired
4.7.2、遍历每个类中被@Autowrited修饰的元素
4.7.2.1、在辅助类的inject方法中为每个元素生成赋值语句(值中Activity的getIntent获取或者从Fragement的getArguments获取)
4.7.3、将方法inject加入辅助类helper中,结合文件生成器mFiler生成此辅助类
InterceptorProcessor
InterceptorProcessor是处理@Interceptor注解的注解处理器。
@AutoService(Processor.class)
@SupportedAnnotationTypes(ANNOTATION_TYPE_INTECEPTOR)
public class InterceptorProcessor extends BaseProcessor {
//拦截器表,key是拦截器优先级,value是被@Interceptor修饰的元素
private Map interceptors = new TreeMap<>();
//拦截器IInterceptor类型信息对象
private TypeMirror iInterceptor = null;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
//初始化拦截器注解处理器InterceptorProcessor
//获取IInterceptor类型信息对象
iInterceptor = elementUtils.getTypeElement(Consts.IINTERCEPTOR).asType();
logger.info(">>> InterceptorProcessor init. <<<");
}
/**
* {@inheritDoc}
*
* @param annotations
* @param roundEnv
*/
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
//执行InterceptorProcessor注解处理器处理程序
if (CollectionUtils.isNotEmpty(annotations)) {
//如果存在注解
//从编译环境对象中获取被@Interceptor注解修饰的所有元素
Set extends Element> elements = roundEnv.getElementsAnnotatedWith(Interceptor.class);
try {
//调用parseInterceptors方法解析被@Interceptor注解修饰的所有元素
parseInterceptors(elements);
} catch (Exception e) {
logger.error(e);
}
return true;
}
return false;
}
/**
* Parse interceptor.
*
* @param elements elements of interceptor.
*/
private void parseInterceptors(Set extends Element> elements) throws IOException {
//解析被@Interceptor注解修饰的所有元素
if (CollectionUtils.isNotEmpty(elements)) {
//如果存在被@Interceptor修饰的元素,则:
logger.info(">>> Found interceptors, size is " + elements.size() + " <<<");
// Verify and cache, sort incidentally.
for (Element element : elements) {
//遍历被@Interceptor注解修饰的元素
if (verify(element)) { // Check the interceptor meta
//校验@Interceptor注解修饰的元素是否合法,如果合法则:
logger.info("A interceptor verify over, its " + element.asType());
//获取元素中@Interceptor 的注解对象
Interceptor interceptor = element.getAnnotation(Interceptor.class);
//从拦截器表中获取与此拦截器的优先级一样的拦截器元素
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())
);
}
//表示没有重复优先级的拦截器,则将此元素加入拦截器表中,key是拦截器优先级,value是被@Interceptor修饰的元素
interceptors.put(interceptor.priority(), element);
} else {
logger.error("A interceptor verify failed, its " + element.asType());
}
}
// Interface of ARouter.
//获取Arouter类型元素对象
TypeElement type_IInterceptor = elementUtils.getTypeElement(IINTERCEPTOR);
//获取拦截器组接口IInterceptorGroup类型元素对象
TypeElement type_IInterceptorGroup = elementUtils.getTypeElement(IINTERCEPTOR_GROUP);
/**
* Build input type, format as :
*
* ```Map>```
*/
//生成拦截器组InterceptorGroup类中的loadInto方法的参数类型:Map>
ParameterizedTypeName inputMapTypeOfTollgate = ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(Integer.class),
ParameterizedTypeName.get(
ClassName.get(Class.class),
WildcardTypeName.subtypeOf(ClassName.get(type_IInterceptor))
)
);
// Build input param name.
//生成拦截器组InterceptorGroup类中的loadInto方法的参数类型及名称:Map> interceptors
ParameterSpec tollgateParamSpec = ParameterSpec.builder(inputMapTypeOfTollgate, "interceptors").build();
// Build method : 'loadInto'
//生成拦截器组InterceptorGroup类中的loadInto方法的builder对象,方法参数为:Map> interceptors
MethodSpec.Builder loadIntoMethodOfTollgateBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
.addAnnotation(Override.class)
.addModifiers(PUBLIC)
.addParameter(tollgateParamSpec);
// Generate
if (null != interceptors && interceptors.size() > 0) {
//如果拦截器表不为空,则:
// Build method body
for (Map.Entry entry : interceptors.entrySet()) {
//变量拦截器表
//为拦截器组的loadInto方法添加语句,将拦截器加入拦截器表interceptors中,key是拦截器的优先级,value是拦截器实现类的class对象
loadIntoMethodOfTollgateBuilder.addStatement("interceptors.put(" + entry.getKey() + ", $T.class)", ClassName.get((TypeElement) entry.getValue()));
}
}
// Write to disk(Write file even interceptors is empty.)
//使用上述生成的java类及方法信息,结合文件生成器mFiler生成拦截器表类文件,类名为:ARouter$$Interceptors$$moudleName
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_IInterceptorGroup))
.build()
).build().writeTo(mFiler);
logger.info(">>> Interceptor group write over. <<<");
}
}
/**
* Verify inteceptor meta
*
* @param element Interceptor taw type
* @return verify result
*/
private boolean verify(Element element) {
//校验被@Interceptor注解修饰的元素是否合法
Interceptor interceptor = element.getAnnotation(Interceptor.class);
// It must be implement the interface IInterceptor and marked with annotation Interceptor.
//如果元素有@Interceptor注解且元素实现了IInterceptor接口,则合法,否则不合法
return null != interceptor && ((TypeElement) element).getInterfaces().contains(iInterceptor);
}
}
根据上述源码解析,我们对拦截器注解处理器得出如下结论:
1、拦截器注解处理器会为每个模块生成一个拦截器表类文件,类名为:ARoutermoudleName
2、拦截器表类实现IInterceptorGroup接口,且其内部也进只有一个loadInto方法,用于向拦截器表中添加本模块内的所有拦截器
3、模块内的拦截器不允许优先级一样的拦截存在
4、@Interceptor只能用于修饰实现了IInterceptor接口
5、注解器生成模块拦截器表类的步骤:
5.1、从编译环境中读取被@Interceptor修饰的所有元素列表
5.2、遍历被@Interceptor修饰的所有元素,过滤模块内优先级重复的拦截器,并把拦截器放入拦截器表中,拦截表key是拦截器的优先级,value是拦截器的元素
5.3、生成模块模块拦截器表类实现的loadInto方法Builder及方法参数对象:Map
5.4、遍历拦截器表
5.4.1、为本模块拦截器表类中loadInto方法添加语句:interceptors.put(interceptorPriority, interceptor.class),即把模块内的拦截器的class加入全局拦截器表中
5.5、使用生成的拦截器表类的方法,结合文件生成器mFiler生成本模块的拦截器组类,类名为:ARoutermoudleName