ARouter原理解析之注解处理器

前言

路由作为项目组件化的基础,其重要程度不言而喻,这里我们就来一起学习阿里开源的路由框架 ARouter(一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦);

对应github地址:https://github.com/alibaba/ARouter

ARouter源码结构

我们将代码下载到本地,目录结构如下:
ARouter目录结构
主要模块功能:

  • arouter-annotation :相关注解模块;涉及的注解有Route【路由跳转】、Interceptor【路由拦截器】、Autowired【参数传递】;
  • arouter-api:ARouter 框架的 API,方法调用的核心;
  • arouter-compiler :编译器对注解的处理库;

以demo为例,当运行项目后会在build文件下生成arouter相关代码;
编译后自动生成的文件
我们接下来也就主要围绕这三个模块进行源码分析;

注解处理器源码解析

arouter-compiler有三个Processor,均继承自BaseProcessor;
1.RouteProcesser – 处理@Autowired, @Route;
2.InterceptorProcessor – 处理@Interceptor;
3.AutowiredProcessor – 处理@Autowired;

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();
        types = processingEnv.getTypeUtils();
        elementUtils = processingEnv.getElementUtils();
        typeUtils = new TypeUtils(types, elementUtils);
        logger = new Logger(processingEnv.getMessager());

        // module name,使用arouter-compiler的module都要配置build.gradle,否则抛出exception
        Map<String, String> 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_]+", "");
            ...
        } else {
            logger.error(NO_MODULE_NAME_TIPS);
  			...
        }
    }
    ...
}

RouteProcesser源码分析

RouteProcesser.process

 if (CollectionUtils.isNotEmpty(annotations)) {
            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;

我们再重点关注parseRoutes(routeElements)这个方法,比较长;

   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();

            TypeMirror type_Activity = elementUtils.getTypeElement(ACTIVITY).asType();
            TypeMirror type_Service = elementUtils.getTypeElement(SERVICE).asType();
            TypeMirror fragmentTm = elementUtils.getTypeElement(FRAGMENT).asType();
            TypeMirror fragmentTmV4 = elementUtils.getTypeElement(Consts.FRAGMENT_V4).asType();

            // Interface of ARouter
            TypeElement type_IRouteGroup = elementUtils.getTypeElement(IROUTE_GROUP);
            TypeElement type_IProviderGroup = elementUtils.getTypeElement(IPROVIDER_GROUP);
            ClassName routeMetaCn = ClassName.get(RouteMeta.class);
            ClassName routeTypeCn = ClassName.get(RouteType.class);

            // 创建参数类型 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))
                    )
            );

            // 创建参数类型 Map<String, RouteMeta>
            ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(
                    ClassName.get(Map.class),
                    ClassName.get(String.class),
                    ClassName.get(RouteMeta.class)
            );

            // 创建方法参数 routes, atlas, providers
            ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, "routes").build();
            ParameterSpec groupParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "atlas").build();
            ParameterSpec providerParamSpec = ParameterSpec.builder(inputMapTypeOfGroup, "providers").build();  // Ps. its param type same as groupParamSpec!

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

            // 遍历所有申明的 @Route
            for (Element element : routeElements) {
                TypeMirror tm = element.asType();
                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)) {
                    // Get all fields annotation by @Autowired
                    Map<String, Integer> paramsType = new HashMap<>();
                    Map<String, Autowired> injectConfig = new HashMap<>();

                    //【遍历解析@Autowired属性,根据 @Autowired 声明的名字做key, 缓存数据类型的 index 值,存入paramsType】
                    injectParamCollector(element, paramsType, injectConfig);
                    // 创建 RouteMeta 对象
                    if (types.isSubtype(tm, type_Activity)) {
                        // Activity
                        logger.info(">>> Found activity route: " + tm.toString() + " <<<");
                        routeMeta = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType);
                    } else {
                        // Fragment
                        logger.info(">>> Found fragment route: " + tm.toString() + " <<<");
                        routeMeta = new RouteMeta(route, element, RouteType.parse(FRAGMENT), paramsType);
                    }

                    routeMeta.setInjectConfig(injectConfig);
                } else if (types.isSubtype(tm, iProvider)) {         // IProvider
                    logger.info(">>> Found provider route: " + tm.toString() + " <<<");
                    routeMeta = new RouteMeta(route, element, RouteType.PROVIDER, null);
                } else if (types.isSubtype(tm, type_Service)) {           // Service
                    logger.info(">>> Found service route: " + tm.toString() + " <<<");
                    routeMeta = new RouteMeta(route, element, RouteType.parse(SERVICE), null);
                } else {
                    throw new RuntimeException("The @Route is marked on unsupported class, look at [" + tm.toString() + "].");
                }
                // 这个方法就是把 route 按照 group 分组保存到 groupMap( Map<String, Set<RouteMeta>>
                categories(routeMeta);
            }
            // 声明这个方法 public void loadInto(Map<String, RouteMeta> providers)
            MethodSpec.Builder loadIntoMethodOfProviderBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
                    .addAnnotation(Override.class)
                    .addModifiers(PUBLIC)
                    .addParameter(providerParamSpec);

            Map<String, List<RouteDoc>> docSource = new HashMap<>();

            // 开始生成代码, 遍历刚才生成的 groupMap
            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);

                List<RouteDoc> routeDocList = new ArrayList<>();

               // 遍历 group 内保存的 routes
                Set<RouteMeta> 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
                            List<? extends TypeMirror> interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces();
                            // 生成方法内代码, 例如下面
                            // providers.put("com.alibaba.android.arouter.demo.testservice.HelloService", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/service/hello", "service", null, -1, -2147483648));
                            for (TypeMirror tm : interfaces) {
                                routeDoc.addPrototype(tm.toString());

                                if (types.isSameType(tm, iProvider)) {   // Its implements iProvider interface himself.
                                    // This interface extend the IProvider, so it can be used for mark provider
                                    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,
                                            routeMeta.getPath(),
                                            routeMeta.getGroup());
                                } else if (types.isSubtype(tm, iProvider)) {
                                    // This interface extend the IProvider, so it can be used for mark provider
                                    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,
                                            routeMeta.getPath(),
                                            routeMeta.getGroup());
                                }
                            }
                            break;
                        default:
                            break;
                    }

                    // 生成配置的参数类型 map
                    // 例如 : put("pac", 9); put("obj", 10); put("name", 8); put("boy", 0);
                    StringBuilder mapBodyBuilder = new StringBuilder();
                    Map<String, Integer> paramsType = routeMeta.getParamsType();
                    Map<String, Autowired> injectConfigs = routeMeta.getInjectConfig();
                    if (MapUtils.isNotEmpty(paramsType)) {
                        List<RouteDoc.Param> paramList = new ArrayList<>();

                        for (Map.Entry<String, Integer> types : paramsType.entrySet()) {
                            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);
                    }
                    String mapBody = mapBodyBuilder.toString();
                    // 生成方法内代码
                    // atlas.put("/test/activity2", RouteMeta.build(RouteType.ACTIVITY, Test2Activity.class, "/test/activity2", "test", new java.util.HashMap<String, Integer>(){{put("key1", 8); }}, -1, -2147483648));
                    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,
                            routeMeta.getPath().toLowerCase(),
                            routeMeta.getGroup().toLowerCase());

                    routeDoc.setClassName(className.toString());
                    routeDocList.add(routeDoc);
                }

                // 生成 java 文件, 例如 ARouter$$Group$$test.java, ARouter$$Group$$service.java
                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);
                docSource.put(groupName, routeDocList);
            }
            // 生成 ARouter$$Root$$app.java 里的代码
            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<String, String> entry : rootMap.entrySet()) {

                    // 生成代码 : routes.put("service", ARouter$$Group$$service.class);
                    loadIntoMethodOfRootBuilder.addStatement("routes.put($S, $T.class)", entry.getKey(), ClassName.get(PACKAGE_OF_GENERATE_FILE, entry.getValue()));
                }
            }

            // Output route doc
            if (generateDoc) {
                docWriter.append(JSON.toJSONString(docSource, SerializerFeature.PrettyFormat));
                docWriter.flush();
                docWriter.close();
            }

            // 生成 providers java 文件. 例如 ARouter$$Providers$$app.java
            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 + " <<<");

            // 生成 root java 文件. 例如 ARouter$$Root$$app.java
            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)))
                            .addModifiers(PUBLIC)
                            .addMethod(loadIntoMethodOfRootBuilder.build())
                            .build()
            ).build().writeTo(mFiler);

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

最终生成文件代码:

public class ARouter$$Group$$test implements IRouteGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> atlas) {
    atlas.put("/test/activity1", RouteMeta.build(RouteType.ACTIVITY, Test1Activity.class, "/test/activity1", "test", new java.util.HashMap<String, Integer>(){{put("ser", 9); put("ch", 5); put("fl", 6); put("dou", 7); put("boy", 0); put("url", 8); put("pac", 10); put("obj", 11); put("name", 8); put("objList", 11); put("map", 11); put("age", 3); put("height", 3); }}, -1, -2147483648));
    atlas.put("/test/activity2", RouteMeta.build(RouteType.ACTIVITY, Test2Activity.class, "/test/activity2", "test", new java.util.HashMap<String, Integer>(){{put("key1", 8); }}, -1, -2147483648));
    atlas.put("/test/activity3", RouteMeta.build(RouteType.ACTIVITY, Test3Activity.class, "/test/activity3", "test", new java.util.HashMap<String, Integer>(){{put("name", 8); put("boy", 0); put("age", 3); }}, -1, -2147483648));
    atlas.put("/test/activity4", RouteMeta.build(RouteType.ACTIVITY, Test4Activity.class, "/test/activity4", "test", null, -1, -2147483648));
    atlas.put("/test/fragment", RouteMeta.build(RouteType.FRAGMENT, BlankFragment.class, "/test/fragment", "test", new java.util.HashMap<String, Integer>(){{put("ser", 9); put("pac", 10); put("ch", 5); put("obj", 11); put("fl", 6); put("name", 8); put("dou", 7); put("boy", 0); put("objList", 11); put("map", 11); put("age", 3); put("height", 3); }}, -1, -2147483648));
    atlas.put("/test/webview", RouteMeta.build(RouteType.ACTIVITY, TestWebview.class, "/test/webview", "test", null, -1, -2147483648));
  }

/**
 * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Group$$yourservicegroupname implements IRouteGroup {
  @Override
  public void loadInto(Map<String, RouteMeta> atlas) {
    atlas.put("/yourservicegroupname/hello", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/yourservicegroupname/hello", "yourservicegroupname", null, -1, -2147483648));
    atlas.put("/yourservicegroupname/json", RouteMeta.build(RouteType.PROVIDER, JsonServiceImpl.class, "/yourservicegroupname/json", "yourservicegroupname", null, -1, -2147483648));
    atlas.put("/yourservicegroupname/single", RouteMeta.build(RouteType.PROVIDER, SingleService.class, "/yourservicegroupname/single", "yourservicegroupname", null, -1, -2147483648));
  }
}
}

总结RouteProcessor做了那些事:

  • 根据 @Route 配置 path, group 生成 ARouter$$Root$$"moduleName"
  • ARouter$$Root$$xxxx.java 以 group 为 key, 注入了生成的 ARouter$$Group$$xxxx 类
  • 根据 @Route 配置 生成 ARouter$$Providers$$"groupName" 和 ARouter$$Group$$"groupName"
  • ARouter$$Providers$$xxxx.java 以类为 key, 注入了 IProvider 接口的实现类
  • ARouter$$Group$$xxxx.java 以 path 为 key, 注入 RouteMate实例, 描述实现类和 @Autowired 参数描述
    RouteProcessor完成了ARouter注解解析生成代码大部分工作;

InterceptorProcessor源码分析

InterceptorProcessor.process方法

 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;

parseInterceptors方法

     private void parseInterceptors(Set<? extends Element> elements) throws IOException {
        if (CollectionUtils.isNotEmpty(elements)) {
            logger.info(">>> Found interceptors, size is " + elements.size() + " <<<");

            // Verify and cache, sort incidentally.
            for (Element element : elements) {
               // 验证必需实现了 IInterceptor 接口
                if (verify(element)) {
                    logger.info("A interceptor verify over, its " + element.asType());
                    Interceptor interceptor = element.getAnnotation(Interceptor.class);

                    // 根据配置 @Interceptor 的 priority, 返回是否有重复配置的拦截器, 如果有抛出错误
                    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 = elementUtils.getTypeElement(IINTERCEPTOR);
            TypeElement type_ITollgateGroup = elementUtils.getTypeElement(IINTERCEPTOR_GROUP);

            // 声明类型 Map<Integer, Class<? extends ITollgate>>
            ParameterizedTypeName inputMapTypeOfTollgate = ParameterizedTypeName.get(
                    ClassName.get(Map.class),
                    ClassName.get(Integer.class),
                    ParameterizedTypeName.get(
                            ClassName.get(Class.class),
                            WildcardTypeName.subtypeOf(ClassName.get(type_ITollgate))
                    )
            );

            // 方法参数 interceptors
            ParameterSpec tollgateParamSpec = ParameterSpec.builder(inputMapTypeOfTollgate, "interceptors").build();

            // 声明方法 loadInto
            MethodSpec.Builder loadIntoMethodOfTollgateBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)
                    .addAnnotation(Override.class)
                    .addModifiers(PUBLIC)
                    .addParameter(tollgateParamSpec);

            // 生成方法内代码, 例如 : interceptors.put(7, Test1Interceptor.class);
            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()));
                }
            }

            // 生成 Interceptor 的注入代码, 继承了 IInterceptorGroup. 例如 ARouter$$Interceptors$$app.java
            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. <<<");
        }
    }

最终生成文件代码:

 * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
public class ARouter$$Interceptors$$modulejava implements IInterceptorGroup {
  @Override
  public void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptors) {
    interceptors.put(7, Test1Interceptor.class);
    interceptors.put(90, TestInterceptor90.class);
  }
}

InterceptorProcessor 就是生成注入拦截器的代码, 拦截器有优先级, 并且一个优先级只能一个拦截器;

AutowiredProcessor注解处理器源码分析
 public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
      categories(roundEnvironment.getElementsAnnotatedWith(Autowired.class));
      generateHelper();
  }
  
private void categories(Set<? extends Element> elements) throws IllegalAccessException {
          for (Element element : elements) {
              TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
              
              // @Autowired不能修饰 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)) {
                  parentAndChild.get(enclosingElement).add(element);
              } else {
                  List<Element> childs = new ArrayList<>();
                  childs.add(element);
                  parentAndChild.put(enclosingElement, childs);
              }
          }
  }

private void generateHelper() throws IOException, IllegalAccessException {
      // 声明方法参数 Object target
      ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build();

          // 遍历前面分析后的 parentAndChild
          for (Map.Entry<TypeElement, List<Element>> entry : parentAndChild.entrySet()) {

              // 声明方法 public void inject(Object target)
              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("."));

              // 类名 : com.alibaba.android.arouter.demo.testactivity.Test1Activity
              // 生成 : com.alibaba.android.arouter.demo.testactivity.Test1Activity$$ARouter$$Autowired
              String fileName = parent.getSimpleName() + NAME_OF_AUTOWIRED;

              // 声明 public class Test1Activity$$ARouter$$Autowired implements ISyringe
              TypeSpec.Builder helper = TypeSpec.classBuilder(fileName)
                      .addJavadoc(WARNING_TIPS)
                      .addSuperinterface(ClassName.get(type_ISyringe))
                      .addModifiers(PUBLIC);

              // 声明变量 private SerializationService serializationService;
              FieldSpec jsonServiceField = FieldSpec.builder(TypeName.get(type_JsonService.asType()), "serializationService", Modifier.PRIVATE).build();
              helper.addField(jsonServiceField);

              // 生成代码 : serializationService = (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();
                  if (types.isSubtype(element.asType(), iProvider)) { 
                      if ("".equals(fieldConfig.name())) {

                          // 生成代码 : substitute.helloService = (HelloService)ARouter.getInstance().navigation(HelloService.class);
                          injectMethodBuilder.addStatement(
                                  "substitute." + fieldName + " = $T.getInstance().navigation($T.class)",
                                  ARouterClass,
                                  ClassName.get(element.asType())
                          );
                      } else {
                          // 生成代码 : substitute.helloService = (HelloService)ARouter.getInstance().build("/test/hello").navigation();
                          injectMethodBuilder.addStatement(
                                  "substitute." + fieldName + " = ($T)$T.getInstance().build($S).navigation();",
                                  ClassName.get(element.asType()),
                                  ARouterClass,
                                  fieldConfig.name()
                          );
                      }

                  } else {  
                      String statment = "substitute." + fieldName + " = substitute.";
                      boolean isActivity = false;
                      if (types.isSubtype(parent.asType(), activityTm)) {
                          isActivity = true;
                          // activity  直接用getIntent()
                          statment += "getIntent().";
                      } else if (types.isSubtype(parent.asType(), fragmentTm) || types.isSubtype(parent.asType(), fragmentTmV4)) {
                          // fragment  直接用getArguments()
                          statment += "getArguments().";
                      } 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.")) { 
                          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());
                      }
                  }
              }


              helper.addMethod(injectMethodBuilder.build());

              // 生成 Autowired 的注入代码, 继承了 ISyringe. 例如 Test1Activity$$ARouter$$Autowired.java
              JavaFile.builder(packageName, helper.build()).build().writeTo(mFiler);
          }
  }

总结

编译期 arouter-compiler 负责生成了注入的的一些代码;

  • ARouter$$Group$$group-name 以 group-name 为文件名注入该 group 下声明了@Route的信息
  • ARouter$$Root$$app 按照 group分组注入了ARouter$$Group$$group-name
  • ARouter$$Providers$$app 注入实现IProvider接口的信息
  • ARouter$$Interceptors$$app 注入实现IInterceptor接口信息
  • Test1Activity$$ARouter$$Autowired@Autowired自动注入的实现

下一节我们接着学习ARouter源码,分析如何实现activity间的跳转逻辑ARouter原理解析之路由跳转

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值