阿里路由框架--ARouter 源码解析之Compiler

来源:互联网 发布:mp4转gif mac 编辑:程序博客网 时间:2024/06/06 02:29

转载请注明出处:http://blog.csdn.net/crazy1235/article/details/77126904


    • 注解处理器的处理流程
    • RouteProcessor
      • init
      • process
      • parseRoutes
      • categories
      • routeVerify
    • InterceptorProcessor
      • init
      • process
      • parseInterceptors
      • verify
    • AutowiredProcessor
      • init
      • process
      • categories
      • generateHelper
    • 总结
    • 参考

前段时间,公司项目在做组件化重构,过程中当然会有很多痛点。

组件化最重要的是根据项目和业务进行分模块,至于模块的粒度就看大家自己来把控了!

这里要说的就是模块之间的数据传输问题

组件化之后,各个模块不相互依赖,那么怎么相互跳转和传递数据呢?

答案就是通过隐式Intent 的方式来跳转和传递数据。

以往的显示Intent 跳转,会存在类直接依赖的问题,这样会导致耦合性非常严重;相比而言,隐式Intent则不需要类之间的直接依赖,但是会出现规则集中式管理,扩展性比较差。

所以在调研期间就发现阿里开源了ARouter–路由框架。

ARouter的好处我这里就不多说,大家可以去看官方文档或者去github上看README。

https://github.com/alibaba/ARouter


接下来会分为若干篇blog来分析一下ARouter的源码!

看了ARouter的源码就会发现,它提供了两个SDK,一个是API,一个Compiler。

  • Compiler SDK 是用于编译器生成相关类文件的。

  • API SDK 是用在运行期间路由跳转等作用的。


这里写图片描述

这里先说说Compiler层SDK。

  • RouteProcessor 路由路径处理器

  • InterceptorProcessor 拦截器处理器

  • AutowireProcessor 自动装配处理器


注解处理器的处理流程

这里写图片描述

(图片转自网络)

实际上,Compiler SDK 只是处根据扫描到的注解生成相应的映射(java)文件。

最后一步通过固定包名加载映射文件是由API SDK来做的。

以官方demo为例来说:

这里写图片描述

上图所示就是ARouter在编译期间生成的类文件。

  • 红色标注的是 RouteProcessor 生成的类文件

  • 蓝色标注的是 InterceptorProcessor 生成的类文件

  • 橙色标书的是 AutowiredProcessor 生成的类文件

arouter-compiler的目录结构如下:

这里写图片描述

  • processor包下面是注解处理器

  • utils包下面是相关工具类

下面分别说说这三种注解处理器:


用过编译时注解的朋友们都知道,注解处理器需要继承AbstractProcessor ,主要涉及的函数有 init()process() 这两个。

RouteProcessor

类的继承信息:

@AutoService(Processor.class)@SupportedOptions(KEY_MODULE_NAME)@SupportedSourceVersion(SourceVersion.RELEASE_7)@SupportedAnnotationTypes({ANNOTATION_TYPE_ROUTE, ANNOTATION_TYPE_AUTOWIRED})public class RouteProcessor extends AbstractProcessor {

init

init()

    // 初始化处理器    @Override    public synchronized void init(ProcessingEnvironment processingEnv) {        super.init(processingEnv);        // 文件管理器        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.        // 获取用户配置的[moduleName]        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 {            // 如果没有在build.gradle中配置moduleName,则会抛出异常。            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 = elements.getTypeElement(Consts.IPROVIDER).asType();        // RouterProcessor 初始化完毕        logger.info(">>> RouteProcessor init. <<<");    }
// Consts.javapublic static final String KEY_MODULE_NAME = "moduleName";

在使用ARouter注解的时候,按照官方文档是需要在每个module里面的build.gradle中配置如下信息:

javaCompileOptions {            annotationProcessorOptions {                arguments = [ moduleName : project.getName() ]            }        }

配置这个属性的目的,就是为了在编译期间生成相关module下的文件和存储文件名称。


process()

一般在process()函数中做的操作如下:

  • 遍历注解的元素

  • 检验元素是否符合要求(过滤元素)

  • 获取输出类参数

  • 生成映射文件(java文件)

  • 错误处理

    @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... <<<");                // 调用arseRoute()函数进行处理获取的注解元素集合                this.parseRoutes(routeElements);            } catch (Exception e) {                logger.error(e);            }            // 如果有Route元素的注解,并且处理过程中无异常则返回true            return true;        }        // 否则返回false        return false;    }

parseRoutes()

这个函数的代码有点长,大家耐心看!

    // Consts.java    public static final String ACTIVITY = "android.app.Activity";    public static final String FRAGMENT = "android.app.Fragment";    public static final String FRAGMENT_V4 = "android.support.v4.app.Fragment";    public static final String SERVICE = "android.app.Service";    private static final String FACADE_PACKAGE = "com.alibaba.android.arouter.facade";    private static final String TEMPLATE_PACKAGE = ".template";    public static final String IROUTE_GROUP = FACADE_PACKAGE + TEMPLATE_PACKAGE + ".IRouteGroup";    public static final String IPROVIDER_GROUP = FACADE_PACKAGE + TEMPLATE_PACKAGE + ".IProviderGroup";
private void parseRoutes(Set<? extends Element> routeElements) throws IOException {        if (CollectionUtils.isNotEmpty(routeElements)) {            // ...            rootMap.clear();            // 获取ACTIVITY, SERVICE, FRAGMENT, FRAGMENT_V4 这四种 类型镜像            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();            // ARouter的接口            TypeElement type_IRouteGroup = elements.getTypeElement(IROUTE_GROUP);            TypeElement type_IProviderGroup = elements.getTypeElement(IPROVIDER_GROUP);            //             // 下面就是遍历获取的注解信息,通过javapoet来生成类文件了             ClassName routeMetaCn = ClassName.get(RouteMeta.class);            ClassName routeTypeCn = ClassName.get(RouteType.class);            /*               ParameterizedTypeName用来创建类型对象,例如下面               ```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))                    )            );            /*                RouteMeta封装了路由相关的信息              ```Map<String, RouteMeta>```             */            ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(                    ClassName.get(Map.class),                    ClassName.get(String.class),                    ClassName.get(RouteMeta.class)            );            /*              创建输入参数             */            // 1。 生成的参数:Map<String, Class<? extends IRouteGroup>> routes            ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, "routes").build(); // 第一个参数表示参数类型,第二个函数表示参数名称            // 2。 Map<String, RouteMeta> atlas            ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "atlas").build();            // 3。 Map<String, RouteMeta> providers            ParameterSpec providerParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "providers").build();              // MethodSpec用来创建方法            // public static final String METHOD_LOAD_INTO = "loadInto";            /*              Build method : 'loadInto'             */            MethodSpec.Builder loadIntoMethodOfRootBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)                    .addAnnotation(Override.class) // override                    .addModifiers(PUBLIC) // public                    .addParameter(rootParamSpec); // 参数            // 创建出来的函数如下            /**             *    @Override             *    public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) { }                */             //            // 接下来的代码就是遍历注解元素,进行分组,进而声称java文件            for (Element element : routeElements) { // 遍历每个元素                TypeMirror tm = element.asType();                Route route = element.getAnnotation(Route.class);                RouteMeta routeMete = null;                // 判断类型                if (types.isSubtype(tm, type_Activity)) {  // Activity                    logger.info(">>> Found activity route: " + tm.toString() + " <<<");                    Map<String, Integer> paramsType = new HashMap<>();                    // 遍历查找所有添加 @AutoWired 注解的变量                    for (Element field : element.getEnclosedElements()) {                        // 1. 必须是field                        // 2. 必须有注解AutoWired                        // 3. 必须不是IProvider类型                        if (field.getKind().isField() && field.getAnnotation(Autowired.class) != null && !types.isSubtype(field.asType(), iProvider)) {                            // 满足上述条件后,获取注解                            Autowired paramConfig = field.getAnnotation(Autowired.class);                            // 看过源码就知道,Autowired支持写别名,当指定name属性之后,就会以name为准,否则以field的名字为准。                            // TypeUtils是自定义工具类,用来判断field的数据类型的,转换成int值。                            paramsType.put(StringUtils.isEmpty(paramConfig.name()) ? field.getSimpleName().toString() : paramConfig.name(), typeUtils.typeExchange(field));                        }                    // 构建一条路由信息,将字段注解信息保存进去                    routeMete = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType);                }                 // 如果是IProvider类型的注解,则直接创建一条PROVIDER类型的路由信息                else if (types.isSubtype(tm, iProvider)) {                             routeMete = new RouteMeta(route, element, RouteType.PROVIDER, null);                }                 // 如果是Service类型的注解,则直接创建一条Service类型的路由信息                else if (types.isSubtype(tm, type_Service)) {           // Service                    routeMete = new RouteMeta(route, element, RouteType.parse(Service), null);                }                 // 如果是fragmentTmV4类型的注解,则直接创建一条Fragment类型的路由信息                else if (types.isSubtype(tm, fragmentTm) || types.isSubtype(tm, fragmentTmV4)) {                    routeMete = new RouteMeta(route, element, RouteType.parse(FRAGMENT), null);                }                // 将路由信息进行分组 (每个路由信息对象中都保存着它所属的组别信息,在调用categories()函数之前所有的组别信息都是默认值"" )                categories(routeMete);            }            // 第一次遍历之前,已经创建了ROOT类的loadInto函数            // 下面开始创建Provider类的loadInto函数            MethodSpec.Builder loadIntoMethodOfProviderBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)                    .addAnnotation(Override.class)                    .addModifiers(PUBLIC)                    .addParameter(providerParamSpec);            // 创建出来的函数如下            /**             *    @Override             *    public void loadInto(Map<String, RouteMeta> providers) { }                */                     // 接着,遍历所有在 categories(routeMete); 得到的所有组别            for (Map.Entry<String, Set<RouteMeta>> entry : groupMap.entrySet()) {                String groupName = entry.getKey();                // 创建分组类的函数 -- loadInto(Map<String, RouteMeta> atlas)                MethodSpec.Builder loadIntoMethodOfGroupBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)                        .addAnnotation(Override.class)                        .addModifiers(PUBLIC)                        .addParameter(groupParamSpec);                // 往组别函数loadInto中添加数据                Set<RouteMeta> groupData = entry.getValue();                // PROVIDERL 类型的数据需要特殊处理                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)) {             // 这种情况下,在loadInfo()函数里面添加的语句类似于:            // singleService直接实现IProvider接口            /**             * @Route(path = "/service/single")             * public class SingleService implements IProvider             *              * providers.put("com.alibaba.android.arouter.demo.testservice.SingleService", RouteMeta.build(RouteType.PROVIDER, SingleService.class, "/service/single", "service", null, -1, -2147483648));                */                                                                        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());                                } else if (types.isSubtype(tm, iProvider)) {                                    // 如果是接口继承的IProvider            // 这种情况下,在loadInfo()函数里面添加的语句类似于:            // singleService直接实现IProvider接口            /**             * @Route(path = "/service/hello")             * public class HelloServiceImpl implements HelloService              * public interface HelloService extends IProvider             * //             * providers.put("com.alibaba.android.arouter.demo.testservice.HelloService", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/service/hello", "service", null, -1, -2147483648));                */                                                                                   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.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("); ");                        }                    }                    // // 形式如: put("pac", 9); put("obj", 10);                    String mapBody = mapBodyBuilder.toString();                    // 往loadInto函数里面添加一个语句                    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, // RouteMeta                            routeTypeCn, // RouteType                            ClassName.get((TypeElement) routeMeta.getRawType()), // 注解原生类的名称                            routeMeta.getPath().toLowerCase(), // 完整路径                            routeMeta.getGroup().toLowerCase()); // 组名                }                // 添加的语句如下:                // atlas.put("/test/activity1", RouteMeta.build(RouteType.ACTIVITY, Test1Activity.class, "/test/activity1", "test", new java.util.HashMap<String, Integer>(){{put("pac", 9); put("obj", 10); put("name", 8); put("boy", 0); put("age", 3); put("url", 8); }}, -1, -2147483648));                // 生成组类别java文件                // public static final String NAME_OF_GROUP = PROJECT + SEPARATOR + "Group" + SEPARATOR;                // public static final String SEPARATOR = "$$";                // public static final String PROJECT = "ARouter";                String groupFileName = NAME_OF_GROUP + groupName;                JavaFile.builder(PACKAGE_OF_GENERATE_FILE, // package 名称 --"com.alibaba.android.arouter.routes"                        TypeSpec.classBuilder(groupFileName) //java类名                                .addJavadoc(WARNING_TIPS) // doc                                .addSuperinterface(ClassName.get(type_IRouteGroup)) // 添加继承的接口                                .addModifiers(PUBLIC) // 作用域为public                                .addMethod(loadIntoMethodOfGroupBuilder.build()) // 添加函数(包括了函数里面的代码块)                                .build()                ).build().writeTo(mFiler);                // 将组名和组文件名放到map中,方便按需加载                rootMap.put(groupName, groupFileName);            }        // .................................................................... //            // 经过了上面的for循环,生成了如 ARouter$$Group$$service.java 和ARouter$$Group$$test.java 文件,它们所在的包是 com.alibaba.android.arouter.routes。            if (MapUtils.isNotEmpty(rootMap)) {                // 遍历这些group,进而生成Root类文件                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()));                    // 每一个statement如: routes.put("test", ARouter$$Group$$test.class);                }            }            // 生成provider类文件            // provider文件名为:ARouter$$Providers$$xxx            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);            // 生成root文件            // ARouter$$Root$$xxx            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);        }    }

categories()

下面来看一下怎么讲路由进行分组的

private void categories(RouteMeta routeMete) {        // 首先去验证这条路由信息        if (routeVerify(routeMete)) {            // 尝试从groupMap中通过group名称获取路由信息            Set<RouteMeta> routeMetas = groupMap.get(routeMete.getGroup());            if (CollectionUtils.isEmpty(routeMetas)) { // 如果map中没有相关记录,则表示这个组别还未添加到map中                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;                        }                    }                });                // 添加该组别到map中                routeMetaSet.add(routeMete);                groupMap.put(routeMete.getGroup(), routeMetaSet);            } else { // 如果存在该组别则添加到这一组中                routeMetas.add(routeMete);            }        } else {            // 验证路由信息不正确是会在编译期间输出错误日志            logger.warning(">>> Route meta verify error, group is " + routeMete.getGroup() + " <<<");        }    }

routeVerify()

// 验证路由信息的正确性private boolean routeVerify(RouteMeta meta) {        String path = meta.getPath();        // 判断路径是否为空或者是否以“/”开头        if (StringUtils.isEmpty(path) || !path.startsWith("/")) {   // The path must be start with '/' and not empty!            return false;        }        // 没有分组时,group为""        if (StringUtils.isEmpty(meta.getGroup())) { // Use default group(the first word in path)            try {                // 截取字符串获取group                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;    }

通过上面的分析可以得到以下几点:

  • 配置Route注解时,路径不允许为空且必须以“/”开头

  • RouteProcessor注解处理器生成的文件由三种:

1. ARouter$$Group$$xxx  (可能有多个)2. ARouter$$Providers$$xxx (只有一个)3. ARouter$$Root$$xxx (只有一个)

InterceptorProcessor

@AutoService(Processor.class)@SupportedOptions(KEY_MODULE_NAME)@SupportedSourceVersion(SourceVersion.RELEASE_7)@SupportedAnnotationTypes(ANNOTATION_TYPE_INTECEPTOR)public class InterceptorProcessor extends AbstractProcessor

init()

    @Override    public synchronized void init(ProcessingEnvironment processingEnv) {        super.init(processingEnv);        // ... 省略代码与RouteProcressor基本一样        iInterceptor = elementUtil.getTypeElement(Consts.IINTERCEPTOR).asType();    }

process()

    @Override    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {        if (CollectionUtils.isNotEmpty(annotations)) {            // 获取Interceptor注解的集合            Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Interceptor.class);            try {                // 处理注解信息                parseInterceptors(elements);            } catch (Exception e) {                logger.error(e);            }            return true;        }        return false;    }

parseInterceptors()

private Map<Integer, Element> interceptors = new TreeMap<>();
private void parseInterceptors(Set<? extends Element> elements) throws IOException {        if (CollectionUtils.isNotEmpty(elements)) {            // 遍历注解元素            for (Element element : elements) {                if (verify(element)) {  // 做验证                    Interceptor interceptor = element.getAnnotation(Interceptor.class);                    // 尝试从拦截器结合中根据优先级获取                    Element lastInterceptor = interceptors.get(interceptor.priority());                    // 如果是已经存在相同优先级的拦截器,就会抛出异常                    if (null != lastInterceptor) {                         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());                }            }            // Interface of ARouter.            TypeElement type_ITollgate = elementUtil.getTypeElement(IINTERCEPTOR);            TypeElement type_ITollgateGroup = elementUtil.getTypeElement(IINTERCEPTOR_GROUP);            /**             *  创建类型对象             *             *  ```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))                    )            );            // 构建输入参数            ParameterSpec tollgateParamSpec = ParameterSpec.builder(inputMapTypeOfTollgate, "interceptors").build();            // 创建函数 : 'loadInto'            MethodSpec.Builder loadIntoMethodOfTollgateBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)                    .addAnnotation(Override.class)                    .addModifiers(PUBLIC)                    .addParameter(tollgateParamSpec);            // 遍历拦截器结合,往loadInto函数中添加语句            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()));                // 语句类似于                // interceptors.put(1, Test1Interceptor.class);                }            }            // 写入文件            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. <<<");        }    }

verify()

// 验证注解元素是否合格private boolean verify(Element element) {        Interceptor interceptor = element.getAnnotation(Interceptor.class);        return null != interceptor && ((TypeElement)element).getInterfaces().contains(iInterceptor);    }

通过上面的分析可以得到以下几点:

  • 不能设置相同优先级的拦截器,否则会抛出异常

  • InterceptorProcessor生成的类文件格式为:

ARouter$$Interceptors$$xxx

AutowiredProcessor

@AutoService(Processor.class)@SupportedOptions(KEY_MODULE_NAME)@SupportedSourceVersion(SourceVersion.RELEASE_7)@SupportedAnnotationTypes({ANNOTATION_TYPE_AUTOWIRED})public class AutowiredProcessor extends AbstractProcessor

init()

    @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.    }

process()

    // process函数主要关注两点 categories() 和 generateHelper()    @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;    }

categories

private Map<TypeElement, List<Element>> parentAndChild = new HashMap<>();
// 将注解元素分组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 autowired fields CAN NOT BE 'private'!!! please check field ["                            + element.getSimpleName() + "] in class [" + enclosingElement.getQualifiedName() + "]");                }                // 判断集合中是否存在集合中                if (parentAndChild.containsKey(enclosingElement)) { // Has categries                    parentAndChild.get(enclosingElement).add(element);                } else {                    List<Element> childs = new ArrayList<>();                    childs.add(element);                    parentAndChild.put(enclosingElement, childs);                }            }            logger.info("categories finished.");        }    }

generateHelper

    //     private void generateHelper() throws IOException, IllegalAccessException {        // ISyringe        TypeElement type_ISyringe = elements.getTypeElement(ISYRINGE);        // SerializationService        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();        // 构建输入参数        ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build();        // 遍历分组的集合        if (MapUtils.isNotEmpty(parentAndChild)) {            for (Map.Entry<TypeElement, List<Element>> entry : parentAndChild.entrySet()) {                // 构建函数 : '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("."));                // 文件名称例如:Test1Activity$$ARouter$$Autowired                String fileName = parent.getSimpleName() + NAME_OF_AUTOWIRED;                //                 TypeSpec.Builder helper = TypeSpec.classBuilder(fileName)                        .addJavadoc(WARNING_TIPS)                        .addSuperinterface(ClassName.get(type_ISyringe))                        .addModifiers(PUBLIC);                // 构建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));                // 转换对象                // 比如:Test1Activity substitute = (Test1Activity)target;                injectMethodBuilder.addStatement("$T substitute = ($T)target", ClassName.get(parent), ClassName.get(parent));                // 遍历注解变量                for (Element element : childs) {                    Autowired fieldConfig = element.getAnnotation(Autowired.class);                    String fieldName = element.getSimpleName().toString();                    // 判断是否是IProvider类型                    if (types.isSubtype(element.asType(), iProvider)) {                          // 如果name为空,则通过Type方式                        if ("".equals(fieldConfig.name())) {                             injectMethodBuilder.addStatement(                                    "substitute." + fieldName + " = $T.getInstance().navigation($T.class)",                                    ARouterClass,                                    ClassName.get(element.asType())                            );                        } else {   // 如果name不为空,则通过name方式                            injectMethodBuilder.addStatement(                                    "substitute." + fieldName + " = ($T)$T.getInstance().build($S).navigation();",                                    ClassName.get(element.asType()),                                    ARouterClass,                                    fieldConfig.name()                            );                        }                        // 是否是必须传值字段,这里加入了if判断                        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 statment = "substitute." + fieldName + " = substitute.";                        boolean isActivity = false;                        // Activity类型时,通过 getIntent() 方式                        if (types.isSubtype(parent.asType(), activityTm)) {                              isActivity = true;                            statment += "getIntent().";                        }                        // Fragment类型, 使用 getArguments()                         else if (types.isSubtype(parent.asType(), fragmentTm) || types.isSubtype(parent.asType(), fragmentTmV4)) {                               statment += "getArguments().";                        }                         // 非Activity或者非Fragment,则抛出异常                        else {                            throw new IllegalAccessException("The field [" + fieldName + "] need autowired from intent, its parent must be activity or fragment!");                        }                        statment = buildStatement(statment, typeUtils.typeExchange(element), isActivity);                        // 针对SerializationService添加判空操作                        if (statment.startsWith("serializationService.")) {   // Not mortals                            injectMethodBuilder.beginControlFlow("if (null != serializationService)");                            injectMethodBuilder.addStatement(                                    "substitute." + fieldName + " = " + statment,                                    (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(statment, 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();                        }                    }                }                // 往类中添加inject() 函数                helper.addMethod(injectMethodBuilder.build());                // 写入文件                JavaFile.builder(packageName, helper.build()).build().writeTo(mFiler);            }            logger.info(">>> Autowired processor stop. <<<");        }    }

AutowiredProcessor生成的java文件举例如下:

public class Test1Activity$$ARouter$$Autowired implements ISyringe {  private SerializationService serializationService;  @Override  public void inject(Object target) {    serializationService = ARouter.getInstance().navigation(SerializationService.class);;    Test1Activity substitute = (Test1Activity)target;    substitute.name = substitute.getIntent().getStringExtra("name");    substitute.age = substitute.getIntent().getIntExtra("age", 0);    substitute.girl = substitute.getIntent().getBooleanExtra("boy", false);    substitute.pac = substitute.getIntent().getParcelableExtra("pac");    if (null != serializationService) {      substitute.obj = serializationService.json2Object(substitute.getIntent().getStringExtra("obj"), TestObj.class);    } else {      Log.e("ARouter::", "You want automatic inject the field 'obj' in class 'Test1Activity' , then you should implement 'SerializationService' to support object auto inject!");    }    substitute.url = substitute.getIntent().getStringExtra("url");    substitute.helloService = ARouter.getInstance().navigation(HelloService.class);  }}

总结

至此,ARouter之Compiler SDK中的三种注解处理器都分析完毕!

接下来的文章开始分析API SDK的源码!

敬请期待~


参考

https://yq.aliyun.com/articles/71687

原创粉丝点击