日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【EventBus】事件通信框架 ( 订阅方法注册 | 检查订阅方法缓存 | 反射获取订阅类中的订阅方法 )

發(fā)布時間:2025/6/17 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【EventBus】事件通信框架 ( 订阅方法注册 | 检查订阅方法缓存 | 反射获取订阅类中的订阅方法 ) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 一、檢查訂閱方法緩存
  • 二、反射獲取訂閱類中的訂閱方法
  • 三、完整代碼示例





一、檢查訂閱方法緩存



注冊訂閱者時 , 只傳入一個訂閱者類對象 , 其它信息都需要通過反射獲取 ;

1. 獲取訂閱者類 : 通過反射獲取該訂閱者類中的所有訂閱方法 , 凡是訂閱方法 , 都帶有 @MySubscribe 注解 ;

// 獲取訂閱者所屬類Class<?> clazz = subscriber.getClass();

2. 查看方法緩存 : 查看方法緩存中 , 是否有該訂閱者對應(yīng)的 訂閱類 和 訂閱方法 信息 ;

// 獲取 Class<?> clazz 參數(shù)類型對應(yīng)的 訂閱者封裝類List<MySubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);

3. 沒有緩存 : METHOD_CACHE 緩存中獲取的 訂閱者封裝類 集合 , 如果該集合為空 , 則說明這是首次獲取該 訂閱者類 中的 訂閱方法 , 需要反射獲取 Class<?> subscriberClass 中的所有訂閱方法 ;

if (subscriberMethods == null) {// 說明是首次獲取 , 初始化 METHOD_CACHE 緩存// 反射獲取 Class<?> subscriberClass 中的所有訂閱方法subscriberMethods = findByReflection(subscriberClass);if (! subscriberMethods.isEmpty()) {METHOD_CACHE.put(subscriberClass, subscriberMethods);}}

4. 有緩存 : METHOD_CACHE 緩存中獲取的 訂閱者封裝類 集合 , 如果該集合不為空 , 說明 則直接返回該集合 ;

if (subscriberMethods == null) {} else {// 如果當(dāng)前不是第一次獲取, 則直接返回從 METHOD_CACHE 緩存中獲取的 訂閱者封裝類 集合return subscriberMethods;}

部分代碼示例 :

/*** 根據(jù)訂閱方法的事件參數(shù)查找訂閱方法* @param subscriberClass 訂閱者對象的類型* @return*/private List<MySubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {// 獲取 Class<?> clazz 參數(shù)類型對應(yīng)的 訂閱者封裝類List<MySubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);// 此處后期重構(gòu), 減少縮進(jìn)if (subscriberMethods == null) {// 說明是首次獲取 , 初始化 METHOD_CACHE 緩存// 反射獲取 Class<?> subscriberClass 中的所有訂閱方法subscriberMethods = findByReflection(subscriberClass);if (! subscriberMethods.isEmpty()) {METHOD_CACHE.put(subscriberClass, subscriberMethods);}} else {// 如果當(dāng)前不是第一次獲取, 則直接返回從 METHOD_CACHE 緩存中獲取的 訂閱者封裝類 集合return subscriberMethods;}// 該分支走不到return null;}



二、反射獲取訂閱類中的訂閱方法



1. 獲取所有方法 : 先通過反射獲取訂閱類中所有方法

// 通過反射獲取所有帶 @MySubscribe 注解的方法Method[] methods = subscriberClass.getMethods();

2. 獲取方法信息 : 獲取方法的修飾符 , 以及方法的參數(shù)集合 ; 之后要使用這兩個值判定方法是否是訂閱方法 ;

// 獲取方法修飾符int modifiers = method.getModifiers();// 獲取方法參數(shù)Class<?>[] params = method.getParameterTypes();

3. 判定方法 : 修飾符必須是 public , 參數(shù)長度必須是 1 , 保證此前提下 , 開始驗證是否有 @MySubscribe 注解 ;

// 確保修飾符必須是 public , 參數(shù)長度必須是 1if (modifiers == Modifier.PUBLIC && params.length == 1) {

4. 獲取注解 : 在修飾符是 public , 參數(shù)長度為 111 的前提下 ; 調(diào)用 Method 對象的 getAnnotation 方法 , 獲取指定 Class 類型的注解 ; 如果獲取的注解不為空 , 則該方法必然是 訂閱方法 ;

// 獲取 MySubscribe 注解MySubscribe annotation = method.getAnnotation(MySubscribe.class);

5. 獲取注解屬性 : @MyThreadMode 注解只定義了一個注解屬性 , 就是 threadMode 線程模式 , 可以直接調(diào)用注解對象的 threadMode() 方法 , 獲取注解屬性 ;

// 獲取線程模式MyThreadMode threadMode = annotation.threadMode();

6 . 封裝訂閱方法 : 將 訂閱方法對象 , 線程模式 , 事件參數(shù) 設(shè)置到

// 此時已經(jīng)完全確定該方法是一個訂閱方法 , 直接進(jìn)行封裝MySubscriberMethod subscriberMethod = new MySubscriberMethod(method, // 方法對象threadMode, // 線程模式params[0] // 事件參數(shù));

7. 返回訂閱方法 : 將 訂閱類 中的 所有 訂閱方法 打包 , 放入返回集合中 ;

// 要返回的 MySubscriberMethod 集合List<MySubscriberMethod> subscriberMethods = new ArrayList<>();// 加入到返回集合中subscriberMethods.add(subscriberMethod);

部分代碼示例 :

/*** 通過反射獲取 Class<?> subscriberClass 訂閱方法* @param subscriberClass 訂閱類* @return*/private List<MySubscriberMethod> findByReflection(Class<?> subscriberClass) {// 要返回的 MySubscriberMethod 集合List<MySubscriberMethod> subscriberMethods = new ArrayList<>();// 通過反射獲取所有帶 @MySubscribe 注解的方法Method[] methods = subscriberClass.getMethods();// 遍歷所有的方法 , 查找注解for (Method method : methods) {// 獲取方法修飾符int modifiers = method.getModifiers();// 獲取方法參數(shù)Class<?>[] params = method.getParameterTypes();// 確保修飾符必須是 public , 參數(shù)長度必須是 1if (modifiers == Modifier.PUBLIC && params.length == 1) {// 獲取 MySubscribe 注解MySubscribe annotation = method.getAnnotation(MySubscribe.class);// 獲取注解不為空if (annotation != null) {// 獲取線程模式MyThreadMode threadMode = annotation.threadMode();// 此時已經(jīng)完全確定該方法是一個訂閱方法 , 直接進(jìn)行封裝MySubscriberMethod subscriberMethod = new MySubscriberMethod(method, // 方法對象threadMode, // 線程模式params[0] // 事件參數(shù));// 加入到返回集合中subscriberMethods.add(subscriberMethod);}}}return subscriberMethods;}



三、完整代碼示例



package com.eventbus_demo.myeventbus;import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList;public class MyEventBus {/*** 方法緩存* Key - 訂閱類類型* Value - 訂閱方法 MySubscriberMethod 的集合* 取名與 EventBus 一致*/private static final Map<Class<?>, List<MySubscriberMethod>> METHOD_CACHE = new HashMap<>();/*** 解除注冊時使用* Key - 訂閱者對象* Value - 訂閱者對象中所有的訂閱方法的事件參數(shù)類型集合** 根據(jù)該訂閱者對象 , 查找所有訂閱方法的事件參數(shù)類型 , 然后再到 METHOD_CACHE 中 ,* 根據(jù)事件參數(shù)類型 , 查找對應(yīng)的 MySubscriberMethod 集合* MySubscriberMethod 中封裝 訂閱者對象 + 訂閱方法**/private final Map<Object, List<Class<?>>> typesBySubscriber;/*** Key - 訂閱者方法事件參數(shù)類型* Value - 封裝 訂閱者對象 與 訂閱方法 的 MySubscription 集合* 在構(gòu)造函數(shù)中初始化* CopyOnWriteArrayList 在寫入數(shù)據(jù)時會拷貝一個副本 ,* 寫完之后 , 將引用指向新的副本 ,* 該集合的線程安全級別很高*/private final Map<Class<?>, CopyOnWriteArrayList<MySubscription>> subscriptionsByEventType;/*** 全局單例*/private static MyEventBus instance;private MyEventBus() {subscriptionsByEventType = new HashMap<>();typesBySubscriber = new HashMap<>();}public static MyEventBus getInstance() {if (instance == null) {instance = new MyEventBus();}return instance;}/*** 注冊訂閱者* @param subscriber*/public void register(Object subscriber) {// 獲取訂閱者所屬類Class<?> clazz = subscriber.getClass();// 查找訂閱方法List<MySubscriberMethod> subscriberMethods = findSubscriberMethods(clazz);// 遍歷所有訂閱方法 , 進(jìn)行訂閱// 首先確保查找到的訂閱方法不為空 , 并且個數(shù)大于等于 1 個if (subscriberMethods != null && !subscriberMethods.isEmpty()) {for (MySubscriberMethod method : subscriberMethods) {// 正式進(jìn)行訂閱subscribe(subscriber, method);}}}/*** 根據(jù)訂閱方法的事件參數(shù)查找訂閱方法* @param subscriberClass 訂閱者對象的類型* @return*/private List<MySubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {// 獲取 Class<?> clazz 參數(shù)類型對應(yīng)的 訂閱者封裝類List<MySubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);// 此處后期重構(gòu), 減少縮進(jìn)if (subscriberMethods == null) {// 說明是首次獲取 , 初始化 METHOD_CACHE 緩存// 反射獲取 Class<?> subscriberClass 中的所有訂閱方法subscriberMethods = findByReflection(subscriberClass);if (! subscriberMethods.isEmpty()) {METHOD_CACHE.put(subscriberClass, subscriberMethods);}} else {// 如果當(dāng)前不是第一次獲取, 則直接返回從 METHOD_CACHE 緩存中獲取的 訂閱者封裝類 集合return subscriberMethods;}// 該分支走不到return null;}/*** 通過反射獲取 Class<?> subscriberClass 訂閱方法* @param subscriberClass 訂閱類* @return*/private List<MySubscriberMethod> findByReflection(Class<?> subscriberClass) {// 要返回的 MySubscriberMethod 集合List<MySubscriberMethod> subscriberMethods = new ArrayList<>();// 通過反射獲取所有帶 @MySubscribe 注解的方法Method[] methods = subscriberClass.getMethods();// 遍歷所有的方法 , 查找注解for (Method method : methods) {// 獲取方法修飾符int modifiers = method.getModifiers();// 獲取方法參數(shù)Class<?>[] params = method.getParameterTypes();// 確保修飾符必須是 public , 參數(shù)長度必須是 1if (modifiers == Modifier.PUBLIC && params.length == 1) {// 獲取 MySubscribe 注解MySubscribe annotation = method.getAnnotation(MySubscribe.class);// 獲取注解不為空if (annotation != null) {// 獲取線程模式MyThreadMode threadMode = annotation.threadMode();// 此時已經(jīng)完全確定該方法是一個訂閱方法 , 直接進(jìn)行封裝MySubscriberMethod subscriberMethod = new MySubscriberMethod(method, // 方法對象threadMode, // 線程模式params[0] // 事件參數(shù));// 加入到返回集合中subscriberMethods.add(subscriberMethod);}}}return subscriberMethods;}}

總結(jié)

以上是生活随笔為你收集整理的【EventBus】事件通信框架 ( 订阅方法注册 | 检查订阅方法缓存 | 反射获取订阅类中的订阅方法 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。