美文网首页程序员Android开发经验谈Android技术知识
组件化知识梳理(2) - Arouter 源码分析之 Compl

组件化知识梳理(2) - Arouter 源码分析之 Compl

作者: 泽毛 | 来源:发表于2018-04-13 01:02 被阅读422次

    组件化知识梳理目录

    组件化知识梳理(1) - Arouter 的基本使用
    组件化知识梳理(2) - Arouter 源码分析之 Complier SDK
    组件化知识梳理(3) - Arouter 源码分析之运行时 SDK

    一、概述

    Arouter的源码 https://github.com/alibaba/ARouter 当中,最主要的就是下面这三个部分:注解arouter-annotation、运行时arouter-api和编译时arouter-complier

    Arouter 源码

    1.1 注解 arouter-annotation

    arouter-annotation定义了我们之前在 组件化知识梳理(1) - Arouter 的基本使用
    中使用过的注解:

    • Router:路径路由,2.3.1
    • intercepter:拦截器,2.3.6
    • AutoWired:依赖注入,2.3.7
    注解 arouter-annotation

    1.2 编译时 arouter-complier

    arouter-complier的内部包含了三个注解处理器,用于处理1.1中使用的三种注解,它们都继承于AbstractProcessor,其原理和 Java&Android 基础知识梳理(1) - 注解 中介绍的 编译时处理注解 原理是相同的,最终目的就是通过这三个注解处理器,在 编译期 扫描被标注的文件,然后按照不同的源文件进行分类,按照 固定的命名格式生成映射文件

    编译时 arouter-complier

    以第一篇文章中看到的module-home模块为例,其会通过解析注解创建下面的.java映射文件,并打包到最终的apk当中:

    module-home 创建的映射文件 module-other 创建的映射文件 module-store 创建的映射文件 lib-base 创建的映射文件

    1.3 运行时 arouter-api

    运行时arouter-api所包含的组件可以用下面这张图来表示。
    [图片上传失败...(image-9d4212-1523552507081)]
    从上之下分为四层:

    • Launcher层,包含了开发者可以直接使用的API,例如Arouter.getInstance()...

      Launcher 层
    • Frossard层,包含了三个部分:

      • Service,从意义上讲是将一定的功能和组件封装成接口,并对外提供能力。
      • Callback,回调接口。
      • Template,用于处理在编译期SDK生成的映射文件,这些映射文件会按照Template组件中提供的模板来生成,这样按照一定规则和约束生成的映射文件也方便ARouter在运行时进行读取。
        Frossard 层
    • SDK内部实现:

      • Ware House,主要存储了ARouter在运行期间加载的一些配置文件以及映射关系。
      • Thread,提供异步加载的线程池。
      • Class Tool,解决不同类型的APK兼容问题。
        SDK 内部实现
    • Logistics Center,物流中心,整个SDK的流转以及内部调用都会下沉到这一层,并会按照功能模块进行划分。

      Logistics Center

    二、arouter-complier 详解

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

    2.1 基础知识

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

    关于编译时注解的处理,我们在 Java&Android 基础知识梳理(1) - 注解 文中用一个详细的例子说明了,大家可以看一下,这里我们简要说一下在代码中用到的类的作用:

    • ProcessingEnvironment:用于提供实用的工具类,主要是ElementsTypesFiler这三个。
      • Elements:用来处理Element的工具类,源码中的每个部分都是Element的一个特定类型,其代码程序中的元素,例如包、类、方法,每一个元素代表一个静态的,语言级别的结构,Element是一个interface,它定义了如下的接口:

        Element 定义的接口
        根据类、成员变量等不同,有如下的继承接口 & 实现类:
        Element 的实现类
      • Types:用来处理TypeMirror的工具类。从Element的实现类中,例如TypeElement,我们可以获取类的名称,但你不能获取类的信息,可以通过element.asType()来获取一个ElementTypeMirror,然后获取类的信息。

      • Filer:用来创建文件。

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

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

    2.2 @Route 注解的解析

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

    /**
     * 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,就是创建了下面三个文件:

    module-other 创建的文件
    • ARouter$$Root$$ + 模块名,由于Arouter对于一个模块下的所有组件都是 采用分组加载 的机制,因此该文件存储的是组名,对应的value为该组下所有的组件。
    /**
     * 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当中。
    /**
     * 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的子类。
    /**
     * 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) {
      }
    }
    

    2.3 @Interceptor 注解的解析

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

    @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文件,例如我们在第一章的Demo中的lib-base,创建的文件为:

    @Interceptor 注解创建的文件
    其命名的规则为:Arouter$$Interceptors + 模块名
    /**
     * 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);
      }
    }
    

    2.4 @Autowired 注解的解析

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

    @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.");
            }
        }
    }
    

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

    /**
     * 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方法,依次对各成员变量进行赋值。

    ARouter.getInstance().inject(this);
    

    三、总结

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

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


    更多文章,欢迎访问我的 Android 知识梳理系列:

    相关文章

      网友评论

        本文标题:组件化知识梳理(2) - Arouter 源码分析之 Compl

        本文链接:https://www.haomeiwen.com/subject/ctktkftx.html