0. 概述
BeeHive
是用于
iOS
的
App
子產品化程式設計的架構實作方案,吸收了
Spring
架構
Service
的理念來實作子產品間的
API
耦合。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#01-%E5%9F%BA%E6%9C%AC%E6%9E%B6%E6%9E%84 0.1 基本架構
0.2 實作特性
- 插件化的子產品開發運作架構
- 子產品具體實作與接口調用分離
- 子產品生命周期管理,擴充了應用的系統事件
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#03-%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99 0.3 設計原則
因為基于
Spring
Service
理念,雖然可以使子產品間的具體實作與接口解耦,但無法避免對接口類的依賴關系。
為什麼不使用
invoke
以及動态連結庫技術實作對接口實作的解耦,類似
Apache
DSO
的方式?
主要是考慮學習成本難度以及動态調用實作無法在編譯檢查階段檢測接口參數變更等問題,動态技術需要更高的程式設計門檻要求。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#04-%E9%A1%B9%E7%9B%AE%E5%90%8D%E6%9D%A5%E6%BA%90 0.4 項目名來源
BeeHive
靈感來源于蜂窩。蜂窩是世界上高度子產品化的工程結構,六邊形的設計能帶來無限擴張的可能。是以我們用了
BeeHive
來做為這個項目的命名。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#1-%E6%A8%A1%E5%9D%97%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E7%9A%84%E4%BA%8B%E4%BB%B6 1 子產品生命周期的事件
BeeHive
會給每個子產品提供生命周期事件,用于與
BeeHive
宿主環境進行必要資訊互動,感覺子產品生命周期的變化。
事件分為三種類型:
- 系統事件
- 通用事件
- 業務自定義事件
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#11-%E7%B3%BB%E7%BB%9F%E4%BA%8B%E4%BB%B6 1.1 系統事件
系統事件通常是
Application
生命周期事件,例如
DidBecomeActive
、
WillEnterBackground
等。
系統事件基本工作流如下:
1.2 通用事件
在系統事件的基礎之上,擴充了應用的通用事件,例
1.3 業務自定義事件
如果覺得系統事件、通用事件不足以滿足需要,我們還将事件封裝簡化成
BHAppdelgate
,你可以通過繼承
BHAppdelegate
來擴充自己的事件。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#2-%E6%A8%A1%E5%9D%97%E6%B3%A8%E5%86%8C 2. 子產品注冊
子產品注冊的方式有靜态注冊與動态注冊兩種。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#21-%E9%9D%99%E6%80%81%E6%B3%A8%E5%86%8C 2.1 靜态注冊
通過在
BeeHive.plist
檔案中注冊符合
BHModuleProtocol
協定子產品類:
擴充的通用事件如下:
2.2 動态注冊
@implementation HomeModule
BH_EXPORT_MODULE() // 聲明該類為子產品入口
@end
在子產品入口類實作中 使用
BH_EXPORT_MODULE()
宏聲明該類為子產品入口實作類。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#23-%E5%BC%82%E6%AD%A5%E5%8A%A0%E8%BD%BD 2.3 異步加載
如果設定子產品導出為
BH_EXPORT_MODULE(YES)
,則會在啟動之後第一屏内容展現之前異步執行子產品的初始化,可以優化啟動時時間消耗。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#3-%E7%BC%96%E7%A8%8B%E5%BC%80%E5%8F%91 3. 程式設計開發
BHModuleProtocol
為各個子產品提供了每個子產品可以
Hook
的函數,用于實作插件邏輯以及代碼實作。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#31-%E8%AE%BE%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F 3.1 設定環境變量
通過
context.env
可以判斷我們的應用環境狀态來決定我們如何配置我們的應用。
-(void)modSetup:(BHContext *)context
{
switch (context.env) {
case BHEnvironmentDev:
//....初始化開發環境
break;
case BHEnvironmentProd:
//....初始化生産環境
default:
break;
}
}
3.2 子產品初始化
如果子產品有需要啟動時初始化的邏輯,可以在
modInit
裡編寫,例如子產品注冊一個外部子產品可以通路的
Service
接口
-(void)modInit:(BHContext *)context
{
//注冊子產品的接口服務
[[BeeHive shareInstance] registerService:@protocol(UserTrackServiceProtocol) service:[BHUserTrackViewController class]];
}
3.3 處理系統事件
系統的事件會被傳遞給每個子產品,讓每個子產品自己決定編寫業務處理邏輯,比如
3D-Touch
功能
-(void)modQuickAction:(BHContext *)context
{
[self process:context.shortcutItem handler:context.scompletionHandler];
}
3.4 模間調用
通過處理
Event
編寫各個業務子產品可以實作插件化程式設計,各業務子產品之間沒有任何依賴,
core
與
module
之間通過
event
互動,實作了插件隔離。但有時候我們需要子產品間的互相調用某些功能來協同完成功能。
通常會有三種形式的接口通路形式:
- 基于接口的實作
通路方式(Service
架構實作)Java spring
- 基于函數調用約定實作的
(Export Method
PHP
,extension
的擴充機制)ReactNative
- 基于跨應用實作的
模式(URL Route
iPhone
之間的互訪)App
我們目前實作了第一種方式,後續會逐漸實作後兩種方式。
基于接口
Service
通路的優點是可以編譯時檢查發現接口的變更,進而及時修正接口問題。缺點是需要依賴接口定義的頭檔案,通過子產品增加得越多,維護接口定義的也有一定工作量。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#341-%E5%AE%9A%E4%B9%89%E6%8E%A5%E5%8F%A3 3.4.1 定義接口
@protocol HomeServiceProtocol <NSObject, BHServiceProtocol>
- (void)registerViewController:(UIViewController *)vc title:(NSString *)title iconName:(NSString *)iconName;
@end
3.4.2 注冊 Service
Service
有兩種方式:
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#api%E6%B3%A8%E5%86%8C API
注冊
API
[[BeeHive shareInstance] registerService:@protocol(HomeServiceProtocol) service:[BHViewController class]];
BHService.plist
BHService.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>HomeServiceProtocol</key>
<string>BHViewController</string>
</dict>
</plist>
3.4.3 調用 Service
Service
#import "BHService.h"
id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];
3.5 單例與多例
對于有些場景下,我們通路每個聲明
Service
的對象,希望對象能保留一些狀态,那我們需要聲明這個
Service
對象是一個單例對象。
我們隻需要在
Service
對象中實作事件函數
聲明
-(BOOL) singleton
{
return YES;
}
createService
擷取的對象則為單例對象,如果實作上面函數傳回的是
NO
,則
createService
傳回的是多例。
id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];
3.6 上下文環境Context
- 初始化設定應用的項目資訊,并在各子產品間共享整個應用程式的資訊
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[BHContext shareInstance].env = BHEnvironmentDev; //定義應用的運作開發環境
[BHContext shareInstance].application = application;
[BHContext shareInstance].launchOptions = launchOptions;
[BHContext shareInstance].moduleConfigName = @"BeeHive.bundle/CustomModulePlist";//可選,預設為BeeHive.bundle/BeeHive.plist
[BHContext shareInstance].serviceConfigName = @"BeeHive.bundle/CustomServicePlist";//可選,預設為BeeHive.bundle/BHService.plist
[[BeeHive shareInstance] setContext:[BHContext shareInstance]];
[super application:application didFinishLaunchingWithOptions:launchOptions];
id<HomeServiceProtocol> homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];
if ([homeVc isKindOfClass:[UIViewController class]]) {
UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:(UIViewController*)homeVc];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = navCtrl;
[self.window makeKeyAndVisible];
}
return YES;
}
更多細節可以參考Example用例。
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#4-%E9%9B%86%E6%88%90%E6%96%B9%E5%BC%8F 4. 內建方式
https://github.com/alibaba/BeeHive/blob/master/README-CN.md#cocoapods cocoapods
cocoapods
pod "BeeHive", '1.1.1'