国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

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

2019-10-21 21:48:43
字體:
供稿:網(wǎng)友

前段時(shí)間,公司項(xiàng)目在做組件化重構(gòu),過程中當(dāng)然會(huì)有很多痛點(diǎn)。

組件化最重要的是根據(jù)項(xiàng)目和業(yè)務(wù)進(jìn)行分模塊,至于模塊的粒度就看大家自己來把控了!

這里要說的就是模塊之間的數(shù)據(jù)傳輸問題

組件化之后,各個(gè)模塊不相互依賴,那么怎么相互跳轉(zhuǎn)和傳遞數(shù)據(jù)呢?

答案就是通過隱式Intent 的方式來跳轉(zhuǎn)和傳遞數(shù)據(jù)。

以往的顯示Intent 跳轉(zhuǎn),會(huì)存在類直接依賴的問題,這樣會(huì)導(dǎo)致耦合性非常嚴(yán)重;相比而言,隱式Intent則不需要類之間的直接依賴,但是會(huì)出現(xiàn)規(guī)則集中式管理,擴(kuò)展性比較差。

所以在調(diào)研期間就發(fā)現(xiàn)阿里開源了ARouter–路由框架。

ARouter的好處我這里就不多說,大家可以去看官方文檔或者去github上看README。

【https://github.com/alibaba/ARouter】

接下來會(huì)分為若干篇blog來分析一下ARouter的源碼!

看了ARouter的源碼就會(huì)發(fā)現(xiàn),它提供了兩個(gè)SDK,一個(gè)是API,一個(gè)Compiler。

  • Compiler SDK 是用于編譯器生成相關(guān)類文件的。
  • API SDK 是用在運(yùn)行期間路由跳轉(zhuǎn)等作用的。

阿里路由框架,ARouter,源碼,Compiler

這里先說說Compiler層SDK。

RouteProcessor 路由路徑處理器

InterceptorProcessor 攔截器處理器

AutowireProcessor 自動(dòng)裝配處理器

注解處理器的處理流程

阿里路由框架,ARouter,源碼,Compiler

(圖片轉(zhuǎn)自網(wǎng)絡(luò))

實(shí)際上,Compiler SDK 只是處根據(jù)掃描到的注解生成相應(yīng)的映射(java)文件。

最后一步通過固定包名加載映射文件是由API SDK來做的。

以官方demo為例來說:

阿里路由框架,ARouter,源碼,Compiler

上圖所示就是ARouter在編譯期間生成的類文件。

  • 紅色標(biāo)注的是 RouteProcessor 生成的類文件
  • 藍(lán)色標(biāo)注的是 InterceptorProcessor 生成的類文件
  • 橙色標(biāo)書的是 AutowiredProcessor 生成的類文件

arouter-compiler的目錄結(jié)構(gòu)如下:

阿里路由框架,ARouter,源碼,Compiler

  • processor包下面是注解處理器
  • utils包下面是相關(guān)工具類

下面分別說說這三種注解處理器:

用過編譯時(shí)注解的朋友們都知道,注解處理器需要繼承AbstractProcessor ,主要涉及的函數(shù)有 init(),process() 這兩個(gè)。

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,則會(huì)拋出異常。   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注解的時(shí)候,按照官方文檔是需要在每個(gè)module里面的build.gradle中配置如下信息:

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

配置這個(gè)屬性的目的,就是為了在編譯期間生成相關(guān)module下的文件和存儲(chǔ)文件名稱。

process()

一般在process()函數(shù)中做的操作如下:

  1. 遍歷注解的元素
  2. 檢驗(yàn)元素是否符合要求(過濾元素)
  3. 獲取輸出類參數(shù)
  4. 生成映射文件(java文件)
  5. 錯(cuò)誤處理
 @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... <<<");    // 調(diào)用arseRoute()函數(shù)進(jìn)行處理獲取的注解元素集合    this.parseRoutes(routeElements);   } catch (Exception e) {    logger.error(e);   }   // 如果有Route元素的注解,并且處理過程中無異常則返回true   return true;  }  // 否則返回false  return false; }

parseRoutes()

這個(gè)函數(shù)的代碼有點(diǎn)長,大家耐心看!

 // 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用來創(chuàng)建類型對(duì)象,例如下面    ```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封裝了路由相關(guān)的信息    ```Map<String, RouteMeta>```    */   ParameterizedTypeName inputMapTypeOfGroup = ParameterizedTypeName.get(     ClassName.get(Map.class),     ClassName.get(String.class),     ClassName.get(RouteMeta.class)   );   /*    創(chuàng)建輸入?yún)?shù)    */   // 1。 生成的參數(shù):Map<String, Class<? extends IRouteGroup>> routes   ParameterSpec rootParamSpec = ParameterSpec.builder(inputMapTypeOfRoot, "routes").build(); // 第一個(gè)參數(shù)表示參數(shù)類型,第二個(gè)函數(shù)表示參數(shù)名稱   // 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用來創(chuàng)建方法   // 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); // 參數(shù)   // 創(chuàng)建出來的函數(shù)如下   /**    * @Override    * public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) { }     */    //   // 接下來的代碼就是遍歷注解元素,進(jìn)行分組,進(jìn)而聲稱java文件   for (Element element : routeElements) { // 遍歷每個(gè)元素    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支持寫別名,當(dāng)指定name屬性之后,就會(huì)以name為準(zhǔn),否則以field的名字為準(zhǔn)。       // TypeUtils是自定義工具類,用來判斷field的數(shù)據(jù)類型的,轉(zhuǎn)換成int值。       paramsType.put(StringUtils.isEmpty(paramConfig.name()) ? field.getSimpleName().toString() : paramConfig.name(), typeUtils.typeExchange(field));      }     // 構(gòu)建一條路由信息,將字段注解信息保存進(jìn)去     routeMete = new RouteMeta(route, element, RouteType.ACTIVITY, paramsType);    }     // 如果是IProvider類型的注解,則直接創(chuàng)建一條PROVIDER類型的路由信息    else if (types.isSubtype(tm, iProvider)) {        routeMete = new RouteMeta(route, element, RouteType.PROVIDER, null);    }     // 如果是Service類型的注解,則直接創(chuàng)建一條Service類型的路由信息    else if (types.isSubtype(tm, type_Service)) {   // Service     routeMete = new RouteMeta(route, element, RouteType.parse(Service), null);    }     // 如果是fragmentTmV4類型的注解,則直接創(chuàng)建一條Fragment類型的路由信息    else if (types.isSubtype(tm, fragmentTm) || types.isSubtype(tm, fragmentTmV4)) {     routeMete = new RouteMeta(route, element, RouteType.parse(FRAGMENT), null);    }    // 將路由信息進(jìn)行分組 (每個(gè)路由信息對(duì)象中都保存著它所屬的組別信息,在調(diào)用categories()函數(shù)之前所有的組別信息都是默認(rèn)值"" )    categories(routeMete);   }   // 第一次遍歷之前,已經(jīng)創(chuàng)建了ROOT類的loadInto函數(shù)   // 下面開始創(chuàng)建Provider類的loadInto函數(shù)   MethodSpec.Builder loadIntoMethodOfProviderBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)     .addAnnotation(Override.class)     .addModifiers(PUBLIC)     .addParameter(providerParamSpec);   // 創(chuàng)建出來的函數(shù)如下   /**    * @Override    * public void loadInto(Map<String, RouteMeta> providers) { }     */      // 接著,遍歷所有在 categories(routeMete); 得到的所有組別   for (Map.Entry<String, Set<RouteMeta>> entry : groupMap.entrySet()) {    String groupName = entry.getKey();    // 創(chuàng)建分組類的函數(shù) -- loadInto(Map<String, RouteMeta> atlas)    MethodSpec.Builder loadIntoMethodOfGroupBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)      .addAnnotation(Override.class)      .addModifiers(PUBLIC)      .addParameter(groupParamSpec);    // 往組別函數(shù)loadInto中添加數(shù)據(jù)    Set<RouteMeta> groupData = entry.getValue();    // PROVIDERL 類型的數(shù)據(jù)需要特殊處理    for (RouteMeta routeMeta : groupData) {     switch (routeMeta.getType()) {      case PROVIDER:        List<? extends TypeMirror> interfaces = ((TypeElement) routeMeta.getRawType()).getInterfaces();       // 遍歷當(dāng)前類的接口       for (TypeMirror tm : interfaces) {        // 如果當(dāng)前類直接實(shí)現(xiàn)了IProvider接口        if (types.isSameType(tm, iProvider)) {    // 這種情況下,在loadInfo()函數(shù)里面添加的語句類似于:   // singleService直接實(shí)現(xiàn)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()函數(shù)里面添加的語句類似于:   // singleService直接實(shí)現(xiàn)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函數(shù)里面添加一個(gè)語句     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) // 作用域?yàn)閜ublic        .addMethod(loadIntoMethodOfGroupBuilder.build()) // 添加函數(shù)(包括了函數(shù)里面的代碼塊)        .build()    ).build().writeTo(mFiler);    // 將組名和組文件名放到map中,方便按需加載    rootMap.put(groupName, groupFileName);   }  // .................................................................... //   // 經(jīng)過了上面的for循環(huán),生成了如 ARouter$$Group$$service.java 和ARouter$$Group$$test.java 文件,它們所在的包是 com.alibaba.android.arouter.routes。   if (MapUtils.isNotEmpty(rootMap)) {    // 遍歷這些group,進(jìn)而生成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()));     // 每一個(gè)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()

下面來看一下怎么講路由進(jìn)行分組的

private void categories(RouteMeta routeMete) {  // 首先去驗(yàn)證這條路由信息  if (routeVerify(routeMete)) {   // 嘗試從groupMap中通過group名稱獲取路由信息   Set<RouteMeta> routeMetas = groupMap.get(routeMete.getGroup());   if (CollectionUtils.isEmpty(routeMetas)) { // 如果map中沒有相關(guān)記錄,則表示這個(gè)組別還未添加到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 {   // 驗(yàn)證路由信息不正確是會(huì)在編譯期間輸出錯(cuò)誤日志   logger.warning(">>> Route meta verify error, group is " + routeMete.getGroup() + " <<<");  } }

routeVerify()

// 驗(yàn)證路由信息的正確性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;  }  // 沒有分組時(shí),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; }

通過上面的分析可以得到以下幾點(diǎn):

配置Route注解時(shí),路徑不允許為空且必須以“/”開頭

RouteProcessor注解處理器生成的文件由三種:

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

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)) { // 做驗(yàn)證     Interceptor interceptor = element.getAnnotation(Interceptor.class);     // 嘗試從攔截器結(jié)合中根據(jù)優(yōu)先級(jí)獲取     Element lastInterceptor = interceptors.get(interceptor.priority());     // 如果是已經(jīng)存在相同優(yōu)先級(jí)的攔截器,就會(huì)拋出異常     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);   /**    * 創(chuàng)建類型對(duì)象    *    * ```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))     )   );   // 構(gòu)建輸入?yún)?shù)   ParameterSpec tollgateParamSpec = ParameterSpec.builder(inputMapTypeOfTollgate, "interceptors").build();   // 創(chuàng)建函數(shù) : 'loadInto'   MethodSpec.Builder loadIntoMethodOfTollgateBuilder = MethodSpec.methodBuilder(METHOD_LOAD_INTO)     .addAnnotation(Override.class)     .addModifiers(PUBLIC)     .addParameter(tollgateParamSpec);   // 遍歷攔截器結(jié)合,往loadInto函數(shù)中添加語句   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()

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

通過上面的分析可以得到以下幾點(diǎn):

不能設(shè)置相同優(yōu)先級(jí)的攔截器,否則會(huì)拋出異常

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函數(shù)主要關(guān)注兩點(diǎn) 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();  // 構(gòu)建輸入?yún)?shù)  ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build();  // 遍歷分組的集合  if (MapUtils.isNotEmpty(parentAndChild)) {   for (Map.Entry<TypeElement, List<Element>> entry : parentAndChild.entrySet()) {    // 構(gòu)建函數(shù) : 'inject'    MethodSpec.Builder injectMethodBuilder = MethodSpec.methodBuilder(METHOD_INJECT)      .addAnnotation(Override.class)      .addModifiers(PUBLIC)      .addParameter(objectParamSpec); // 添加參數(shù)    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);    // 構(gòu)建SerializationService 字段    FieldSpec jsonServiceField = FieldSpec.builder(TypeName.get(type_JsonService.asType()), "serializationService", Modifier.PRIVATE).build();    // 添加字段    helper.addField(jsonServiceField);    // inject函數(shù)中添加語句    // serializationService = ARouter.getInstance().navigation(SerializationService.class);    injectMethodBuilder.addStatement("serializationService = $T.getInstance().navigation($T.class);", ARouterClass, ClassName.get(type_JsonService));    // 轉(zhuǎn)換對(duì)象    // 比如: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類型時(shí),通過 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);      // 針對(duì)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() 函數(shù)    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); }}

總結(jié)

至此,ARouter之Compiler SDK中的三種注解處理器都分析完畢!

接下來的文章開始分析API SDK的源碼!以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 鄱阳县| 镇雄县| 延边| 富源县| 呼伦贝尔市| 乳源| 鹤山市| 广水市| 襄垣县| 淅川县| 祁阳县| 和平县| 香河县| 香港| 樟树市| 凤山市| 黎川县| 丹棱县| 沛县| 盐源县| 荆州市| 盖州市| 平罗县| 洪江市| 高陵县| 进贤县| 崇明县| 桂东县| 陆川县| 司法| 高邑县| 鄂尔多斯市| 宁南县| 赤壁市| 炎陵县| 通河县| 曲麻莱县| 新安县| 巴林左旗| 江口县| 科技|