<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] 上一篇文章對 EventBus 進行了整體的源碼分析,看到 EventBus 3.0 獲取訂閱事件的注解信息共有兩種方式,分別是通過 EventBusAnnotationProcessor 注解處理器和運行時通過反射獲取,本文主要對這兩種方式進行源碼分析,并對編譯時注解和運行時注解進行拓展學習。 在 EventBus 的 findSubscriberMethods 方法中可以看到: ```java List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) { ... if (ignoreGeneratedIndex) { subscriberMethods = findUsingReflection(subscriberClass); } else { subscriberMethods = findUsingInfo(subscriberClass); } ... ``` 根據 ignoreGeneratedIndex 的值,分別有通過反射和索引兩種方式尋找訂閱方法,接下來我們一一來看: # 通過反射 findUsingReflection 方法是通過運行時反射來尋找訂閱方法的,來看看它的源碼: ```java private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) { // 用來做訂閱方法的訂閱和保存 FindState findState = prepareFindState(); // 初始化觀察者的 FindState findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { // 通過反射來尋找訂閱方法 findUsingReflectionInSingleClass(findState); // 查找父類的訂閱方法 findState.moveToSuperclass(); } // 獲得 findState 中的訂閱方法 list 并返回 return getMethodsAndRelease(findState); } ``` 接下來看看 findUsingReflectionInSingleClass 方法的源碼: ```java private void findUsingReflectionInSingleClass(FindState findState) { Method[] methods; // 通過反射得到方法數組 try { // This is faster than getMethods, especially when subscribers are fat classes like Activities methods = findState.clazz.getDeclaredMethods(); } catch (Throwable th) { // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149 methods = findState.clazz.getMethods(); findState.skipSuperClasses = true; } // 遍歷 Method for (Method method : methods) { int modifiers = method.getModifiers(); if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { Class<?>[] parameterTypes = method.getParameterTypes(); // 保證必須只有一個事件參數 if (parameterTypes.length == 1) { // 得到注解 Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class); if (subscribeAnnotation != null) { Class<?> eventType = parameterTypes[0]; // 檢查是否添加方法到 findState if (findState.checkAdd(method, eventType)) { ThreadMode threadMode = subscribeAnnotation.threadMode(); // 添加訂閱方法到 findState findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, subscribeAnnotation.priority(), subscribeAnnotation.sticky())); } } } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) { String methodName = method.getDeclaringClass().getName() + "." + method.getName(); throw new EventBusException("@Subscribe method " + methodName + "must have exactly 1 parameter but has " + parameterTypes.length); } } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) { String methodName = method.getDeclaringClass().getName() + "." + method.getName(); throw new EventBusException(methodName + " is a illegal @Subscribe method: must be public, non-static, and non-abstract"); } } } ``` 至此,通過反射獲取到了觀察者的訂閱方法。 # 通過 EventBusAnnotationProcessor 注解處理器 EventBus 3.0 索引使用方法: 要應用我們生成的索引時,需要在構造 EventBus 時傳入我們自定義的 EventBusIndex,如: ```java EventBus mEventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build(); ``` 或者是將索引應用到默認的單例中: ```java EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus(); ``` 接下來我們分析下源碼,首先來看看 findUsingInfo 方法: ```java private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) { FindState findState = prepareFindState(); findState.initForSubscriber(subscriberClass); while (findState.clazz != null) { // 從 findState 中獲取 SubscriberInfo findState.subscriberInfo = getSubscriberInfo(findState); if (findState.subscriberInfo != null) { // 從 subscriberInfo 中獲得訂閱方法數組 SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods(); for (SubscriberMethod subscriberMethod : array) { // 檢查是否添加方法到 findState if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) { // 添加訂閱方法到 findState findState.subscriberMethods.add(subscriberMethod); } } } else { // 通過反射獲取訂閱方法 findUsingReflectionInSingleClass(findState); } // 查找父類的訂閱方法 findState.moveToSuperclass(); } return getMethodsAndRelease(findState); } ``` 看一下關鍵的 getSubscriberInfo 方法: ```java private SubscriberInfo getSubscriberInfo(FindState findState) { if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) { SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo(); if (findState.clazz == superclassInfo.getSubscriberClass()) { return superclassInfo; } } if (subscriberInfoIndexes != null) { for (SubscriberInfoIndex index : subscriberInfoIndexes) { SubscriberInfo info = index.getSubscriberInfo(findState.clazz); if (info != null) { return info; } } } return null; } ``` # 注解處理器的使用 本段轉載自:[Java注解處理器](https://www.race604.com/annotation-processing/) 這篇文章講解注解處理器非常不錯,感興趣可以仔細閱讀。 ## 什么是注解處理器 注解處理器(Annotation Processor)是 javac 的一個工具,它用來在編譯時掃描和處理注解(Annotation)。注解處理器以 Java 代碼(或者編譯過的字節碼)作為輸入,生成文件(通常是 .java 文件)作為輸出。這些生成的 Java 代碼是在生成的 .java 文件中,所以你不能修改已經存在的 Java 類,例如向已有的類中添加方法。這些生成的 Java 文件,會同其他普通的手動編寫的 Java 源代碼一樣被 javac 編譯。 ## AbstractProcessor 每一個注解處理器都是繼承于 AbstractProcessor,如下所示: ```java package com.example; public class MyProcessor extends AbstractProcessor { @Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { } @Override public Set<String> getSupportedAnnotationTypes() { } @Override public SourceVersion getSupportedSourceVersion() { } } ``` * init(ProcessingEnvironment env): 每一個注解處理器類都必須有一個空的構造函數。然而,這里有一個特殊的 init()方法,它會被注解處理工具調用,并輸入 ProcessingEnviroment 參數。ProcessingEnviroment 提供很多有用的工具類 Elements, Types 和 Filer。 * process(Set<? extends TypeElement> annotations, RoundEnvironment env): 這相當于每個處理器的主函數 main()。你在這里寫你的掃描、評估和處理注解的代碼,以及生成 Java 文件。輸入參數 RoundEnviroment,可以讓你查詢出包含特定注解的被注解元素。 * getSupportedAnnotationTypes(): 這里你必須指定,這個注解處理器是注冊給哪個注解的。注意,它的返回值是一個字符串的集合,包含本處理器想要處理的注解類型的合法全稱。換句話說,你在這里定義你的注解處理器注冊到哪些注解上。 * getSupportedSourceVersion(): 用來指定你使用的 Java 版本。通常這里返回 SourceVersion.latestSupported()。然而,如果你有足夠的理由只支持 Java 6的話,你也可以返回 SourceVersion.RELEASE_6。我推薦你使用前者。 在 Java 7中,也可以使用注解來代替 getSupportedAnnotationTypes()和 getSupportedSourceVersion(),像這樣: ```java @SupportedSourceVersion(SourceVersion.latestSupported()) @SupportedAnnotationTypes({ // 合法注解全名的集合 }) public class MyProcessor extends AbstractProcessor { @Override public synchronized void init(ProcessingEnvironment env){ } @Override public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { } } ``` # 總結 經過一天加一個晚上的時間,EventBus 3.0 的源碼分析工作完成了,收獲很多。 EventBus 是對于觀察者模式一個很好的實踐,接下來也要對其他常見設計模式進行系統的學習。注解處理器現在廣泛應用于各個開源庫,通過這次源碼分析,也加深了對于注解的理解。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看