Ctrip 中bus 的使用

在实际的开发中,bus 的使用还是比较多的,对于模块化路由的使用 ,还有模块之间的通讯,于Ctrip 目前项目中的使用,主要是存在2种bus,一种是Ctrip 自己封装的bus 还有一种是使用了开源的EventBus 我们分别来看下他们的实现方式

1  在App 启动的时候,会对bus 进行初始化的配置:

  static void intBusAndBundle(Application application) {
        BusInit busInit = new BusInit();
        //bus manager init
        BusManager.init(busInit);
        //all bundles setted
        configBundles();
        //BundleCore init
        try {
            BundleCore.getInstance().init(application);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

我们看到这个里有BusInit 的类,在程序启动的时候,创建了busInit 的实例,我们看下,该方法中的实际实现:

它实现了 BusObjectProvider 

public interface BusObjectProvider {
    boolean register(BusObject var1);
    BusObject findBusObject(String var1);
    void asyncFindBusObject(Context var1, String var2, AsyncBusObjectCallback var3);
}

看看里面的具体实现方法:

public class BusInit implements BusObjectProvider {

    private static final Map<String, BusObject> hostMap = new HashMap<>();
    private static final Map<String, LoadBusObjectRunnable> hostRunnableMap = new HashMap<>();
    @Override
    public boolean register(BusObject busObject) {
        if (busObject == null) {
            LogUtil.d("Bus", "register BusObject error:" + busObject);
            return false;
        }
        String host = busObject.getHost().toLowerCase();
        if (hostMap.containsKey(host)) {
            LogUtil.d("Bus", host + " :已注册,不可重复注册");
        } else {
            busObject.troogleBundleCreated();
            LogUtil.d("Bus", "troogleBundleCreated on register:" + busObject.getHost() + ", pid:" + Process.myPid());
        }
        hostMap.put(host, busObject);
        return true;
    }

    @Override
    public BusObject findBusObject(String host) {
        if (TextUtils.isEmpty(host)) {
            return null;
        }
        // 同步Load
        BusObject obj = hostMap.get(host.toLowerCase());
        if (obj == null) {
            obj = getBusObjectRunnable(host).doLoad();
            if (obj != null) {
                hostMap.put(host.toLowerCase(), obj);
            }
            LogUtil.d("Bus", "findBusObject inner:" + host + "," + obj);
        }
        return obj;
    }
    private void asyncFindLocalBusObject(final String host, final BusManager.AsyncBusObjectCallback asyncBusObjectCallback) {
        if (TextUtils.isEmpty(host)) {
            if (asyncBusObjectCallback != null) {
                asyncBusObjectCallback.onFindBusObject(null);
            }
        }
        BusObject obj = hostMap.get(host.toLowerCase());
        if (obj == null) {
            String savedHost = host.toLowerCase();
            LoadBusObjectRunnable loadBusObjectRunnable = getBusObjectRunnable(savedHost);
            loadBusObjectRunnable.addBusObjectCallback(asyncBusObjectCallback);
            if (!loadBusObjectRunnable.isRunning()) {
                ThreadUtils.runOnBackgroundThread(loadBusObjectRunnable);
            }
        } else {
            if (asyncBusObjectCallback != null) {
                asyncBusObjectCallback.onFindBusObject(obj);
            }
        }
    }

    private LoadBusObjectRunnable getBusObjectRunnable(String host) {
        if (TextUtils.isEmpty(host)) {
            return null;
        }
        String savedHost = host.toLowerCase();
        LoadBusObjectRunnable loadBusObjectRunnable = hostRunnableMap.get(savedHost);
        if (loadBusObjectRunnable == null) {
            LogUtil.d("BusLoad", "getBusObjectRunnable is null, new Runnable");
            loadBusObjectRunnable = new LoadBusObjectRunnable(savedHost);
            hostRunnableMap.put(savedHost, loadBusObjectRunnable);
        }
        return loadBusObjectRunnable;
    }
    @Override
    public void asyncFindBusObject(final Context context, final String hostName, final BusManager.AsyncBusObjectCallback busObjectCallback) {
        final BundleConfigModel bundleConfigModel = BundleConfigFactory.getBundleConfigModelByModuleName(hostName);
        if (bundleConfigModel != null) {
            if (Package.isMCDPackage() && bundleConfigModel.bundleLoadType == BundleConfigModel.BundleLoadType.RemoteLoad) {
                if (!BundleFacade.isRemotePackageInstall(bundleConfigModel.packageName)) {
                    LogUtil.e("RemotePackageNotInstall");
                    PluginLoaderManager.getInstance().downLoadPlugin(context, bundleConfigModel.packageName, PluginLoaderManager.LOAD_TYPE_FOREGROUND,new PluginLoaderListener() {

                        @Override
                        public void onDownloadSize(int size, int totalSize) {
                            LogUtil.e("remote bundle download:size change-" + size + "," + totalSize);
                        }

                        @Override
                        public void onDownloadSucess() {
                            LogUtil.e("remote bundle download:onDownloadSucess");
                            BusObject obj = findBusObject(hostName);
                            if (obj != null && busObjectCallback != null) {
                                busObjectCallback.onFindBusObject(obj);
                            }
                        }

                        @Override
                        public void onDownLoadFail() {
                            LogUtil.e("remote bundle download:onDownLoadFail");
                        }

                        @Override
                        public boolean install(String filePath) {
                            LogUtil.e("remote bundle download:install-" + filePath);
                            return BundleFacade.remoteLoadInstall(bundleConfigModel.packageName, filePath);
                        }

                    });
                } else {
                    if (PluginLoaderManager.getInstance().hasNewVersionForPlugin(bundleConfigModel.packageName)) {
                        LogUtil.e("hasNewVersionForPlugin");
                        PluginLoaderManager.getInstance().downLoadPlugin(context, bundleConfigModel.packageName, PluginLoaderManager.LOAD_TYPE_FOREGROUND,new PluginLoaderListener() {

                            @Override
                            public void onDownloadSize(int size, int totalSize) {

                            }

                            @Override
                            public void onDownloadSucess() {
                                BusObject obj = findBusObject(hostName);
                                if (obj != null && busObjectCallback != null) {
                                    busObjectCallback.onFindBusObject(obj);
                                }
                            }

                            @Override
                            public void onDownLoadFail() {

                            }

                            @Override
                            public boolean install(String filePath) {
                                return  BundleFacade.remoteLoadUpgrade(bundleConfigModel.packageName,filePath);
                            }
                        });
                    }else {
                        BusObject obj = findBusObject(hostName);
                        if (obj != null && busObjectCallback != null) {
                            LogUtil.e("have not NewVersionForPlugin--busObjectCallback");
                            busObjectCallback.onFindBusObject(obj);
                        }
                    }
                }
            } else {
                asyncFindLocalBusObject(hostName, new BusManager.AsyncBusObjectCallback() {
                    @Override
                    public void onFindBusObject(BusObject busObject) {
                        if (busObject != null && busObjectCallback != null) {
                            LogUtil.e("RemotePackageInstall--busObjectCallback:" + busObject + "," + busObjectCallback);
                            busObjectCallback.onFindBusObject(busObject);
                        }
                    }
                });
            }
        }
    }

}

我们看到该类中提供了  register 和  findBusObject 两个方法,Bus 的bus 的维持方式,在

Map<String, BusObject> hostMap = new HashMap<>();

我们看到方法 

    @Override
    public BusObject findBusObject(String host) {
        if (TextUtils.isEmpty(host)) {
            return null;
        }

        // 同步Load
        BusObject obj = hostMap.get(host.toLowerCase());
        if (obj == null) {
            obj = getBusObjectRunnable(host).doLoad();
            if (obj != null) {
                hostMap.put(host.toLowerCase(), obj);
            }
            LogUtil.d("Bus", "findBusObject inner:" + host + "," + obj);
        }
        return obj;
    }

是寻找Bus 如果要寻找的Bus 不存在,则执行

 obj = getBusObjectRunnable(host).doLoad();

我们看下这个代码中的具体实现:

  private LoadBusObjectRunnable getBusObjectRunnable(String host) {
        if (TextUtils.isEmpty(host)) {
            return null;
        }
        String savedHost = host.toLowerCase();
        LoadBusObjectRunnable loadBusObjectRunnable = hostRunnableMap.get(savedHost);
        if (loadBusObjectRunnable == null) {
            LogUtil.d("BusLoad", "getBusObjectRunnable is null, new Runnable");
            loadBusObjectRunnable = new LoadBusObjectRunnable(savedHost);
            hostRunnableMap.put(savedHost, loadBusObjectRunnable);
        }
        return loadBusObjectRunnable;
    }

可以看出是个  LoadBusObjectRunnable 对象,再看后面的 load() 的方法实现


    public BusObject doLoad() {
        isRunning = true;
        BusObject busObject = registerBusObjectWithHost(hostName);
        isRunning = false;
        actionCallback(busObject);
        return busObject;
    }

我们看到,这里如果是注册 registerBusObjectWithHost(hostName)  这个方法的实现过程,具体分析看源码

 private BusObject registerBusObjectWithHost(String hostName) {
        Tick.start("registerBusObjectWithHost:" + hostName);
        try {
            if (StringUtil.isEmpty(hostName)) {
                return null;
            }
            BusObject retObj = null;
            if (COMMON_HOST_NAME.equalsIgnoreCase(hostName)) {
               // 这里是用 公共带有common 库 
                try {
                    Class<BusObject> clazz = (Class<BusObject>) Class.forName(COMMON_BUS_OBJECT);
                    Constructor<BusObject> constructor = clazz.getConstructor(String.class); //动态获取构造函数
                    BusObject tmpRetObj = constructor.newInstance(hostName);
                    if (Bus.register(tmpRetObj)) {//注册这个object
                        return tmpRetObj;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
           // 这里是rn 的BusObject
            } else if(REACT_NATIVE_Host_Name.equalsIgnoreCase(hostName)) {
                try {
                    Class<BusObject> clazz = (Class<BusObject>) Class.forName(REACT_NATIVE_BUS_OBJECT);
                    Constructor<BusObject> constructor = clazz.getConstructor(String.class);//动态获取构造函数
                    BusObject tmpRetObj = constructor.newInstance(hostName);
                    if (Bus.register(tmpRetObj)) {//注册这个object
                        return tmpRetObj;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

          // 这里是常规的bundle 的方式,首先先验证下所要寻找的bundle包是不是在注册的里,如果不在注册里,返回位null
            BundleConfigModel bundleConfigModel = BundleConfigFactory.getBundleConfigModelByModuleName(hostName);
            if (null == bundleConfigModel) {
                LogUtil.f("BusManager", "getBundleConfigModelByModuleName bundleConfigModel is null :" + bundleConfigModel + "," + hostName);
                return null;
            }
      // 在注册中返回busObjectName,根据bundle 的加载方式,执行不同的策略
            String className = bundleConfigModel.busObjectName;
            if (!StringUtil.isEmpty(className)) {
                LogUtil.d("BusManager", "BusManager执行:" + className);
                try {
                    String packageName = bundleConfigModel.packageName;
                    if (!TextUtils.isEmpty(packageName)) {
                        if (bundleConfigModel.bundleLoadType == BundleConfigModel.BundleLoadType.RemoteLoad) {
                            if (!BundleFacade.isRemotePackageInstall(packageName)) {
                                LogUtil.d("BusManager", "Remoting Load must call asyncCall method");
                            }
                        } else {
                            // 先注入依赖的bundle,加载所依赖的bundle 包
                            if (bundleConfigModel.dependenceList != null) {
                                for(String depBundleName : bundleConfigModel.dependenceList) {
                                    BundleConfigModel model = BundleConfigFactory.getBundleConfigModelByModuleName(depBundleName);
                                    if (model != null) {
                                        BundleFacade.delayLoadInstall(model.packageName);
                                    }
                                }
                            }

                            // 注入当前bundle
                            BundleFacade.delayLoadInstall(packageName);
                        }
                    }
                 // 动态的注入相应的Class
                    Class<BusObject> clazz = (Class<BusObject>) Class.forName(className);
                    Constructor<BusObject> constructor = clazz.getConstructor(String.class);    //动态获取构造函数
                    BusObject tmpRetObj = constructor.newInstance(hostName);
                    if (Bus.register(tmpRetObj)) {//注册这个object
                        retObj = tmpRetObj;
                    }
                } catch (Exception e) {
                    LogUtil.d("BusManager", "create BusObject error:" + e.getMessage());
                    e.printStackTrace();
                    String model = bundleConfigModel.packageName;
                    String logd = ctrip.foundation.util.StringUtil.getDescriptionFromException(e);
                    if (!Env.isTestEnv()) {
                        LogUtil.f("BusManager", "BusManager error:" + logd);
                    }
                    if (!TextUtils.isEmpty(model) && !bundleLogWhiteList.contains(model)) {
                        try {
                            int result = BundleCore.getInstance().ValidBundle(model);
                            Map dic = new HashMap();
                            dic.put("hostName", hostName);
                            dic.put("type", result);
                            dic.put("error", logd);
                            CtripActionLogUtil.logTrace("o_bus_register_error", dic);
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }
                    }
                }
            }
            return retObj;
        } finally {
            Tick.end();
        }
    }

我们看到这个是个系统的Bus  的 注册管理,最终系统的调用是在Bus 的类中使用,我们看下代码中具体实现

public class Bus {


    /**
     * 注册业务对象到总线
     *
     * @param busObject 处理业务job的对象
     * @throws IllegalArgumentException 如果host已被注册,抛出异常不可重复注册
     */
    public synchronized static boolean register(BusObject busObject) {
        return BusManager.register(busObject);
    }


    /**
     * 查找业务总线
     */
    public static BusObject findBusObject(String bizName) {
        return BusManager.findBusObject(bizName);
    }

    /**
     * 数据总线,跨业务模块异步调用
     *
     * @param context        调用上下文。根据调用场景自行决定,常见可选值null/Application/Activity等
     * @param bizName        业务接口名,大小写不敏感
     * @param resultListener 业务job处理完成回调数据
     * @param param          附加参数列表
     */
    public static void asyncCallData(final Context context, final String bizName, final BusObject.AsyncCallResultListener resultListener, final Object... param) {
        BusManager.asyncFindBusObject(context, BusManager.parseBizNameHost(bizName), new BusManager.AsyncBusObjectCallback() {
            @Override
            public void onFindBusObject(BusObject busObject) {
                if (busObject != null) {
                    busObject.doAsyncDataJob(context, bizName, resultListener, param);
                }
            }
        });
    }

    /**
     * 数据总线,跨业务模块同步调用
     *
     * @param context 调用上下文。根据调用场景自行决定,常见可选值null/Application/Activity等
     * @param bizName 业务接口名,大小写不敏感
     * @param param   附加参数
     * @return 直接返回对方接口的返回值
     */
    public static Object callData(Context context, String bizName, Object... param) {
        LogUtil.d("JTIME", "callData:" + bizName);
        try {
            BusObject obj = BusManager.findBusObject(BusManager.parseBizNameHost(bizName));
            if (obj != null) {
                return obj.doDataJob(context, bizName, param);
            } else {
                HashMap<String, String> info = new HashMap<>();
                info.put("bizName", bizName);
                StringBuilder params = new StringBuilder();
                if (param != null && param.length > 0) {
                    for(Object p : param) {
                        params.append(p == null ? "null" : p.getClass() + ":" + p);
                    }
                }
                info.put("params", params.toString());
                LogUtil.logMetrics("o_bus_calldata_not_found", 0, info);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 数据总线,跨业务模块异步调用
     * 寻找BusObject的过程在异步完成,将会触发 callData(用来解决首次bundle异步加载callBus耗时问题)
     */
    public static void callDataOnBackground(final Context context, final String bizName, final BusObject.AsyncCallResultListener resultListener, final Object... param) {
        LogUtil.d("Bus", "callDataOnBackground:" + bizName + "," + resultListener);
        BusManager.asyncFindBusObject(context, BusManager.parseBizNameHost(bizName), new BusManager.AsyncBusObjectCallback() {
            @Override
            public void onFindBusObject(final BusObject busObject) {
                LogUtil.d("Bus", "callDataOnBackground callback:" + bizName + "," + busObject);
                if (busObject != null) {
                    ThreadUtils.post(new Runnable() {
                        @Override
                        public void run() {
                            Object data = busObject.doDataJob(context, bizName, param);
                            if (resultListener != null) {
                                resultListener.asyncCallResult("", data);
                            }
                        }
                    });
                }
            }
        });
    }

    /**
     * URL总线,跨业务模块异步调用(不建议使用)
     *
     * @param context        调用上下文。根据调用场景自行决定,常见可选值null/Application/Activity等
     * @param url            业务url,大小写不敏感
     * @param resultListener 业务job处理完成回调数据
     */
    public static void asyncCallURL(Context context, String url, BusObject.AsyncCallResultListener resultListener) {
        BusObject obj = BusManager.findBusObject(BusManager.parseUrlHost(url));
        if (obj != null) {
            obj.doAsyncURLJob(context, url, resultListener);
        }
    }

    /**
     * URL总线,跨业务模块同步调用
     *
     * @param context 调用上下文。根据调用场景自行决定,常见可选值null/Application/Activity等
     * @param url     业务url,大小写不敏感
     * @return 直接返回对方接口的返回值
     */
    public static Object callURL(Context context, String url) {
        BusObject obj = BusManager.findBusObject(BusManager.parseUrlHost(url));
        if (obj != null) {
            return obj.doURLJob(context, url);
        }

        return null;
    }


}

我们看到CallData 的方法中,的方法调用了方法

 BusObject obj = BusManager.findBusObject(BusManager.parseBizNameHost(bizName));

那我看下 BusManager 的findBusObject 中具体实现方式 


    static BusObject findBusObject(String hostName) {
        return busObjectProvider.findBusObject(hostName);
    }

我们看到,最终会调到上面分析的 busObjectProvider.findBusObject(hostName);  最终是调用到我们上面分析的代码。

2 开源框架 EventBus 

我们先看下EventBus 是如何初始化的

   /** Convenience singleton for apps using a process-wide EventBus instance. */
    public static EventBus getDefault() {
        EventBus instance = defaultInstance;
        if (instance == null) {
            synchronized (EventBus.class) {
                instance = EventBus.defaultInstance;
                if (instance == null) {
                    instance = EventBus.defaultInstance = new EventBus();
                }
            }
        }
        return instance;
    }

我们看下EventBus 是通过构造器的方式去传达

 /**
     * Creates a new EventBus instance; each instance is a separate scope in which events are delivered. To use a
     * central bus, consider {@link #getDefault()}.
     */
    public EventBus() {
        this(DEFAULT_BUILDER);
    }

    EventBus(EventBusBuilder builder) {
        logger = builder.getLogger();
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        stickyEvents = new ConcurrentHashMap<>();
        mainThreadSupport = builder.getMainThreadSupport();
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;

      // 事件background 处理
        backgroundPoster = new BackgroundPoster(this);
        asyncPoster = new AsyncPoster(this);
        indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
        subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                builder.strictMethodVerification, builder.ignoreGeneratedIndex);
        logSubscriberExceptions = builder.logSubscriberExceptions;
        logNoSubscriberMessages = builder.logNoSubscriberMessages;
        sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
        throwSubscriberException = builder.throwSubscriberException;
        eventInheritance = builder.eventInheritance;
        executorService = builder.executorService;
    }

我们看下源码注册过程

 /**
     * Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
     * are no longer interested in receiving events.
     * <p/>
     * Subscribers have event handling methods that must be annotated by {@link Subscribe}.
     * The {@link Subscribe} annotation also allows configuration like {@link
     * ThreadMode} and priority.
     */
    public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
       //通过subscriberMethodFinder 返回一个List ,包含method对象以及将来相应订阅再那个线程的mode 时间的enventType 和 优先级
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

我们来一起看看 findSubscriberMethods 方法中的实现方式

  List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        if (subscriberMethods.isEmpty()) {
            throw new EventBusException("Subscriber " + subscriberClass
                    + " and its super classes have no public methods with the @Subscribe annotation");
        } else {
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
            return subscriberMethods;
        }
    }

我们来看下subscirbe 的实现方式,分享看源码


    // Must be called in synchronized block
    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }

        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);

        if (subscriberMethod.sticky) {
            if (eventInheritance) {
                // Existing sticky events of all subclasses of eventType have to be considered.
                // Note: Iterating over all events may be inefficient with lots of sticky events,
                // thus data structure should be changed to allow a more efficient lookup
                // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry<Class<?>, Object> entry : entries) {
                    Class<?> candidateEventType = entry.getKey();
                    if (eventType.isAssignableFrom(candidateEventType)) {
                        Object stickyEvent = entry.getValue();
                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                    }
                }
            } else {
                Object stickyEvent = stickyEvents.get(eventType);
                checkPostStickyEventToSubscription(newSubscription, stickyEvent);
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/ahubenkui/article/details/81561291