網友zhanglPeng在我一篇部落格評論區邀請我寫一篇BeeHive原理解析,我答應了他,剛好週末有一點點時間,於是抽空看了下BeeHive原始碼寫下這篇文章。如有見解不到之處敬請提出指正。
BeeHive
BeeHive是一款阿里開源應用於iOS工程模組化程式設計框架。吸收了Spring框架 Service的理念來實現模組間的API耦合,原理即是向Mediator註冊Protocol和相應的Impl.
大家來找茬
BeeHive是阿里開源。。裡開源。。開源。。源。。
程式碼我沒細看,稍微看了下實現原理,但是竟然發現兩處明顯命名錯誤
第一處
1 |
[[BHModuleManager sharedManager] tiggerEvent:BHMSetupEvent]; |
tigger
?難道不是trigger
嗎。為了防止自己被打臉,我用了幾款主流翻譯軟體(除滬江小D)得出結果跳跳虎,滬江小D翻譯的結果有一種解釋是觸發器,但觸發器是名詞不是動詞呀。
第二處
1 |
[BeeHive shareInstance].enableExpection = YES; |
這行程式碼作用是讓開發者設定是否允許BeeHive丟擲異常,仔細看Expection(期望)。。。正確的應該是exception
暫時只發現2處,歡迎大家有興趣下載原始碼來找茬。
框架結構
– BHContext
APP上下文物件,記錄APP的API環境等資訊。為了方便讓其他開發者擴充套件配置,BHContext
持有了一個BHConfig
,開發者可以利用BHConfig
提供的API 配置自定義擴充套件資訊,如下圖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@interface BHConfig : NSObject +(instancetype) shareInstance; +(id)get:(NSString *)key; +(BOOL)has:(NSString *)key; +(void) add:(NSDictionary *)parameters; +(NSMutableDictionary *) getAll; +(NSString *)stringValue:(NSString *)key; +(NSDictionary *)dictionaryValue:(NSString *)key; +(NSInteger)integerValue:(NSString *)key; +(float)floatValue:(NSString *)key; ...... |
那麼問題來了,BHContext
持有了一個BHConfig
物件,但是BHConfig
類中提供的均是類方法,我仔細瞄了好幾眼,一個例項方法都沒有,那BHContext
持有的BHConfig
物件有什麼用,+(instancetype) shareInstance;
介面又有什麼用,不理解。
另通過這種方式擴充套件配置資訊會導致一定量的HardCode,帶來維護和使用上的不便。實際效果遠不如BHConfig
中掛一個property看的直觀,而且可能一些公司的應用環境超過了BHEnvironmentType
列舉中列出的環境,也不好擴充。
還有上面程式碼中的函式 -(返回值)和函式名中間有些有空格有些沒空格。作為一個以公司名義開源的框架好歹CodeReview下吧。。。
– BHModuleManager
模組管理器。啟動時需要被BHModuleManager
管理的Module
都會被註冊,且快取了所有被註冊Module
的例項物件.
註冊方式:
##一.動態註冊
需要被動態註冊的Module
,在該Module
的實現檔案.m中,複製巨集BeeHiveMod(ShopModule)
,(具體原理我只瞭解了七七八八就不做過多解釋了,想了解的同學可以去查詢資料..)
在BHModuleManager
中- (void)registedAnnotationModules
方法內,由BHAnnotation
呼叫內部的static NSArray* BHReadConfiguration(char *section)
方法獲取到記憶體中以巨集定義中特殊命名的資料,轉換成Module
的ClassName,再通過runtime構建相應的Module
例項物件進行快取.
##二.載入local pilst
把需要註冊的Module
配置在相應的plist檔案中,也可以配置Module
的level,啟動時載入plist檔案,讀取儲存了Module
的ClassName的list,通過runtime的反射構建需要註冊的Module
例項物件進而快取
##三.主動註冊
在需要註冊的Module
的+ (void)load
方法中呼叫[BeeHive registerDynamicModule:[self class]];
主動註冊
以上註冊方式任意選擇一種,我建議在專案中統一用一種註冊方式.
BHModuleManager
中快取了所有被註冊Module
的一份例項,但是他不對外提供獲取Module
的介面,所以我認為凡是遵守BHModuleProtocol
協議的Module
做的事情僅限於處理系統事件和一些應用事件。他並非我們理解的普通的業務Module
。
Module
不能在外部alloc 出來,因為你即使建立一個新的Module
例項出來,你並不在BHModuleManager
的管理下,是無法接收BHModuleManager
分發的系統事件,建立出來沒有意義。
– BHServiceManager
和BHModuleManager
一樣提供了3種註冊方式,不過只能用其中一種方式註冊,如果同時用2種方式註冊會丟擲異常。
BHServiceManager
對外提供了根據protocol獲取到相應的Impl例項(原理和我第一篇元件化總結-protocol註冊方案一樣),這是BeeHive
最核心的功能。
– BHServiceProtocol
沒什麼可講的,就2個介面
1 2 3 |
-(BOOL)singleton; +(id)shareInstance; |
– BHModuleProtocol
定義的Module
生命週期回撥介面,以及系統事件介面。BHServiceManager
會在接收到系統事件後,分發給所有在他內部管理的並且實現BHModuleProtocol
相應介面的Module
– BeeHive
對外的入口模組,採用了外觀設計模式,BHServiceManager
和BHModuleManager
2個類沒有對外暴露,由BeeHive
對外提供相應的介面,BeeHive
內部呼叫BHServiceManager
和BHModuleManager
相應的介面.
Beehive裡面的程式碼規範包括一些匪夷所思的介面定義,總讓我感覺不像是大廠開源的作品,不過有一些設計思路還是很值得學習借鑑。希望Beehive會越來越好!