本文主要介紹組件化通訊的三種方式
URL路由 ---- MGJRouter
基于URL匹配或者命名約定,通過runtime動(dòng)態(tài)調(diào)用,實(shí)現(xiàn)簡(jiǎn)單,類似系統(tǒng)的openURL
優(yōu)點(diǎn)
- 極高的動(dòng)態(tài)性
- 可以統(tǒng)一管理多平臺(tái)的路由規(guī)則
- 可以適配 URL Scheme
缺點(diǎn)
- 參數(shù)通過字符串形式轉(zhuǎn)換,方式有限,編譯期無法進(jìn)行類型檢測(cè)
- 參數(shù)格式不明確
- 不支持Storyboard
- 無法保證使用模塊一定存在
- 解耦能力有限,url字符串一旦修改會(huì)導(dǎo)致其他地方失效
MGJRouter
- App啟動(dòng)時(shí)實(shí)例化所需的組件模塊,注冊(cè)
url - 需要調(diào)用其他模塊時(shí),傳遞
url和參數(shù),類似系統(tǒng)的openURL
//注冊(cè)u(píng)rl
[MGJRouter registerURLPattern:@"mgj://category/travel" toHandler:^(NSDictionary *routerParameters) {
NSLog(@"routerParameters == %@",routerParameters);
}];
//調(diào)用路由
[MGJRouter openURL:@"mgj://category/travel" withUserInfo:@{@"user_id": @1900} completion:nil];
Target-Action -- CTMediator
基于runtime和category特性,動(dòng)態(tài)獲取模塊,例如通過NSClassFromString獲取實(shí)例,performSelector + NSInvocation動(dòng)態(tài)調(diào)用方法
- 利用分類添加路由接口,通過字符串獲取對(duì)應(yīng)的類
- 通過runtime創(chuàng)建實(shí)例,動(dòng)態(tài)調(diào)用方法
優(yōu)點(diǎn)
- 通過
category明確接口聲明 輕量
缺點(diǎn)
- 模塊化繁瑣,需要在
target、mediator重新添加每個(gè)接口 -
category中通過字符串識(shí)別,存在和URL路由一樣的問題 - 無法保證使用的模塊一定存在,target修改后,運(yùn)行時(shí)才能報(bào)錯(cuò)
CTMediator
在分類中通過調(diào)用performTarget:action:params:shouldCacheTarget:方法,找到對(duì)應(yīng)的target和action
- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget
{
if (targetName == nil || actionName == nil) {
return nil;
}
//在swift中使用時(shí),需要傳入對(duì)應(yīng)項(xiàng)目的target名稱,否則會(huì)找不到視圖控制器
NSString *swiftModuleName = params[kCTMediatorParamsKeySwiftTargetModuleName];
// generate target 生成target
NSString *targetClassString = nil;
if (swiftModuleName.length > 0) {
//swift中target文件名拼接
targetClassString = [NSString stringWithFormat:@"%@.Target_%@", swiftModuleName, targetName];
} else {
//OC中target文件名拼接
targetClassString = [NSString stringWithFormat:@"Target_%@", targetName];
}
//緩存中查找target
NSObject *target = [self safeFetchCachedTarget:targetClassString];
//緩存中沒有target
if (target == nil) {
//通過字符串獲取對(duì)應(yīng)的類
Class targetClass = NSClassFromString(targetClassString);
//創(chuàng)建實(shí)例
target = [[targetClass alloc] init];
}
// generate action 生成action方法名稱
NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName];
//通過方法名字符串獲取對(duì)應(yīng)的sel
SEL action = NSSelectorFromString(actionString);
if (target == nil) {
// 這里是處理無響應(yīng)請(qǐng)求的地方之一,這個(gè)demo做得比較簡(jiǎn)單,如果沒有可以響應(yīng)的target,就直接return了。實(shí)際開發(fā)過程中是可以事先給一個(gè)固定的target專門用于在這個(gè)時(shí)候頂上,然后處理這種請(qǐng)求的
[self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params];
return nil;
}
//是否需要緩存
if (shouldCacheTarget) {
[self safeSetCachedTarget:target key:targetClassString];
}
//是否響應(yīng)sel
if ([target respondsToSelector:action]) {
//動(dòng)態(tài)調(diào)用方法
return [self safePerformAction:action target:target params:params];
} else {
// 這里是處理無響應(yīng)請(qǐng)求的地方,如果無響應(yīng),則嘗試調(diào)用對(duì)應(yīng)target的notFound方法統(tǒng)一處理
SEL action = NSSelectorFromString(@"notFound:");
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target params:params];
} else {
// 這里也是處理無響應(yīng)請(qǐng)求的地方,在notFound都沒有的時(shí)候,這個(gè)demo是直接return了。實(shí)際開發(fā)過程中,可以用前面提到的固定的target頂上的。
[self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params];
@synchronized (self) {
[self.cachedTarget removeObjectForKey:targetClassString];
}
return nil;
}
}
}
-
safePerformAction:target:params:方法的實(shí)現(xiàn),是通過NSInvocation進(jìn)行消息轉(zhuǎn)發(fā)+參數(shù)傳遞
- (id)safePerformAction:(SEL)action target:(NSObject *)target params:(NSDictionary *)params
{
//獲取方法簽名
NSMethodSignature* methodSig = [target methodSignatureForSelector:action];
if(methodSig == nil) {
return nil;
}
//判斷返回類型,根據(jù)返回值完成參數(shù)傳遞
const char* retType = [methodSig methodReturnType];
//void類型
if (strcmp(retType, @encode(void)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
return nil;
}
//NSInteger類型
if (strcmp(retType, @encode(NSInteger)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
NSInteger result = 0;
[invocation getReturnValue:&result];
return @(result);
}
//BOOL類型
if (strcmp(retType, @encode(BOOL)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
BOOL result = 0;
[invocation getReturnValue:&result];
return @(result);
}
//CGFloat類型
if (strcmp(retType, @encode(CGFloat)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
CGFloat result = 0;
[invocation getReturnValue:&result];
return @(result);
}
//NSUInteger類型
if (strcmp(retType, @encode(NSUInteger)) == 0) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setArgument:¶ms atIndex:2];
[invocation setSelector:action];
[invocation setTarget:target];
[invocation invoke];
NSUInteger result = 0;
[invocation getReturnValue:&result];
return @(result);
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
return [target performSelector:action withObject:params];
#pragma clang diagnostic pop
}
Protocol Class -- BeeHive
- 將
protocol和對(duì)應(yīng)的類字典匹配 - 通過
protocol獲取class動(dòng)態(tài)創(chuàng)建
優(yōu)點(diǎn)
- 通過接口調(diào)用,保證參數(shù)類型安全
- 直接使用
protocol接口,無需重復(fù)封裝
缺點(diǎn)
- 不支持swift
- 無法保證使用的Protocol一定存在對(duì)應(yīng)模塊
- 通過框架創(chuàng)建所有對(duì)象,不支持外部傳入?yún)?shù)
BeeHive
BeeHive借鑒了Spring Service、Apache DSO的架構(gòu)理念,采用AOP+擴(kuò)展Application API形式,將業(yè)務(wù)和基礎(chǔ)功能通過模塊方法解耦,模塊直接通過Service形式調(diào)用,避免直接依賴,在AppDelegate中解耦,進(jìn)行邏輯拆分,每個(gè)模塊微應(yīng)用形式獨(dú)立存在
BeeHive 注冊(cè)
BeeHive通過BHModuleManager來管理已經(jīng)被注冊(cè)的模塊
BeeHive提供了三種注冊(cè)方法:.plist、動(dòng)態(tài)注冊(cè)(load)、Annotation
.plist文件
- 設(shè)置
plist文件路徑
[BHContext shareInstance].moduleConfigName = @"BeeHive.bundle/BeeHive";//可選,默認(rèn)為BeeHive.bundle/BeeHive.plist
-
創(chuàng)建
plist文件
image.png loadLocalModules方法讀取plist文件,添加到BHModuleInfos數(shù)組
#pragma mark - Private
//初始化context,加載Modules、Services
-(void)setContext:(BHContext *)context
{
_context = context;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self loadStaticServices];
[self loadStaticModules];
});
}
//加載modules
- (void)loadStaticModules
{
// 讀取本地plist文件里面的Module,并注冊(cè)到BHModuleManager的BHModuleInfos數(shù)組中
[[BHModuleManager sharedManager] loadLocalModules];
//注冊(cè)所有modules,在內(nèi)部根據(jù)優(yōu)先級(jí)進(jìn)行排序
[[BHModuleManager sharedManager] registedAllModules];
}
- (void)loadLocalModules
{
//plist文件路徑
NSString *plistPath = [[NSBundle mainBundle] pathForResource:[BHContext shareInstance].moduleConfigName ofType:@"plist"];
//判斷文件是否存在
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
return;
}
//讀取整個(gè)文件[@"moduleClasses" : 數(shù)組]
NSDictionary *moduleList = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
//通過moduleClasses key讀取 數(shù)組 [[@"moduleClass":"aaa", @"moduleLevel": @"bbb"], [...]]
NSArray<NSDictionary *> *modulesArray = [moduleList objectForKey:kModuleArrayKey];
NSMutableDictionary<NSString *, NSNumber *> *moduleInfoByClass = @{}.mutableCopy;
//遍歷數(shù)組
[self.BHModuleInfos enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[moduleInfoByClass setObject:@1 forKey:[obj objectForKey:kModuleInfoNameKey]];
}];
[modulesArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (!moduleInfoByClass[[obj objectForKey:kModuleInfoNameKey]]) {
//存儲(chǔ)到 BHModuleInfos 中
[self.BHModuleInfos addObject:obj];
}
}];
}
動(dòng)態(tài)注冊(cè)(load)
- 在
load方法中注冊(cè)
+ (void)load
{
[BeeHive registerDynamicModule:[self class]];
}
-
registerDynamicModule方法
+ (void)registerDynamicModule:(Class)moduleClass
{
[[BHModuleManager sharedManager] registerDynamicModule:moduleClass];
}
- (void)registerDynamicModule:(Class)moduleClass
{
[self registerDynamicModule:moduleClass shouldTriggerInitEvent:NO];
}
- (void)registerDynamicModule:(Class)moduleClass
shouldTriggerInitEvent:(BOOL)shouldTriggerInitEvent
{
[self addModuleFromObject:moduleClass shouldTriggerInitEvent:shouldTriggerInitEvent];
}
- 或者通過宏定義
BH_EXPORT_MODULE代替load方法
#define BH_EXPORT_MODULE(isAsync) \
+ (void)load { [BeeHive registerDynamicModule:[self class]]; } \
-(BOOL)async { return [[NSString stringWithUTF8String:#isAsync] boolValue];}
Annotation注冊(cè)
- 通過
BeeHiveMod的宏進(jìn)行Annotation標(biāo)記
//***** 使用
BeeHiveMod(ShopModule)
//***** BeeHiveMod的宏定義
#define BeeHiveMod(name) \
class BeeHive; char * k##name##_mod BeeHiveDATA(BeehiveMods) = ""#name"";
//***** BeeHiveDATA的宏定義
#define BeeHiveDATA(sectname) __attribute((used, section("__DATA,"#sectname" ")))
//***** 全部轉(zhuǎn)換出來后為下面的格式
char * kShopModule_mod __attribute((used, section("__DATA,""BeehiveMods"" "))) = """ShopModule""";
__attribute
第一個(gè)參數(shù)
used:用來修飾函數(shù),被修飾后,意味著即使函數(shù)沒有被引用,在Release下也不會(huì)被優(yōu)化section("__DATA,""BeehiveMods"" "):指定未被優(yōu)化的模塊注入Mach-o的__DATA段BHReadConfiguration方法讀取Mach-o中的數(shù)據(jù)段,取出存放到數(shù)組
NSArray<NSString *>* BHReadConfiguration(char *sectionName,const struct mach_header *mhp)
{
NSMutableArray *configs = [NSMutableArray array];
unsigned long size = 0;
#ifndef __LP64__
// 找到之前存儲(chǔ)的數(shù)據(jù)段(Module找BeehiveMods段 和 Service找BeehiveServices段)的一片內(nèi)存
uintptr_t *memory = (uintptr_t*)getsectiondata(mhp, SEG_DATA, sectionName, &size);
#else
const struct mach_header_64 *mhp64 = (const struct mach_header_64 *)mhp;
uintptr_t *memory = (uintptr_t*)getsectiondata(mhp64, SEG_DATA, sectionName, &size);
#endif
unsigned long counter = size/sizeof(void*);
// 把特殊段里面的數(shù)據(jù)都轉(zhuǎn)換成字符串存入數(shù)組中
for(int idx = 0; idx < counter; ++idx){
char *string = (char*)memory[idx];
NSString *str = [NSString stringWithUTF8String:string];
if(!str)continue;
BHLog(@"config = %@", str);
if(str) [configs addObject:str];
}
return configs;
}
BeeHive模塊事件
BeeHive給每個(gè)模塊提供Application生命周期事件,用于與主程序進(jìn)行必要信息交互,感知模塊生命周期的變化。
所有的Module必須遵守BHModuleProtocol協(xié)議,否則無法接受事件消息
在BHModuleManager中,所有時(shí)間被定義成枚舉BHModuleEventType
typedef NS_ENUM(NSInteger, BHModuleEventType)
{
//設(shè)置Module模塊
BHMSetupEvent = 0,
//用于初始化Module模塊,例如環(huán)境判斷,根據(jù)不同環(huán)境進(jìn)行不同初始化
BHMInitEvent,
//用于拆除Module模塊
BHMTearDownEvent,
BHMSplashEvent,
BHMQuickActionEvent,
BHMWillResignActiveEvent,
BHMDidEnterBackgroundEvent,
BHMWillEnterForegroundEvent,
BHMDidBecomeActiveEvent,
BHMWillTerminateEvent,
BHMUnmountEvent,
BHMOpenURLEvent,
BHMDidReceiveMemoryWarningEvent,
BHMDidFailToRegisterForRemoteNotificationsEvent,
BHMDidRegisterForRemoteNotificationsEvent,
BHMDidReceiveRemoteNotificationEvent,
BHMDidReceiveLocalNotificationEvent,
BHMWillPresentNotificationEvent,
BHMDidReceiveNotificationResponseEvent,
BHMWillContinueUserActivityEvent,
BHMContinueUserActivityEvent,
BHMDidFailToContinueUserActivityEvent,
BHMDidUpdateUserActivityEvent,
BHMHandleWatchKitExtensionRequestEvent,
BHMDidCustomEvent = 1000
};
-
系統(tǒng)事件:Application生命周期
通過將項(xiàng)目的AppDelegate繼承BHAppDelegate
@interface TestAppDelegate : BHAppDelegate <UIApplicationDelegate>

-
應(yīng)用事件:官方給出的流程圖,其中modSetup、modInit等,可以用于編碼實(shí)現(xiàn)各插件模塊的設(shè)置與初始化。
應(yīng)用事件 自定義事件:可以通過調(diào)用BHModuleManager的triggerEvent :方法處理所有事件
- (void)triggerEvent:(NSInteger)eventType
{
[self triggerEvent:eventType withCustomParam:nil];
}
- (void)triggerEvent:(NSInteger)eventType
withCustomParam:(NSDictionary *)customParam {
[self handleModuleEvent:eventType forTarget:nil withCustomParam:customParam];
}
#pragma mark - module protocol
- (void)handleModuleEvent:(NSInteger)eventType
forTarget:(id<BHModuleProtocol>)target
withCustomParam:(NSDictionary *)customParam
{
switch (eventType) {
//初始化事件
case BHMInitEvent:
//special
[self handleModulesInitEventForTarget:nil withCustomParam :customParam];
break;
//析構(gòu)事件
case BHMTearDownEvent:
//special
[self handleModulesTearDownEventForTarget:nil withCustomParam:customParam];
break;
//其他3類事件
default: {
NSString *selectorStr = [self.BHSelectorByEvent objectForKey:@(eventType)];
[self handleModuleEvent:eventType forTarget:nil withSeletorStr:selectorStr andCustomParam:customParam];
}
break;
}
}
從上面代碼發(fā)現(xiàn),除了BHMInitEvent初始化、BHMTearDownEvent析構(gòu)兩個(gè)特殊事件外,所有的事件都是調(diào)用handleModuleEvent:forTarget:withSeletorStr:andCustomParam:,在內(nèi)部通過遍歷moduleInstances數(shù)組,調(diào)用performSelector:withObject:實(shí)現(xiàn)
- (void)handleModuleEvent:(NSInteger)eventType
forTarget:(id<BHModuleProtocol>)target
withSeletorStr:(NSString *)selectorStr
andCustomParam:(NSDictionary *)customParam
{
BHContext *context = [BHContext shareInstance].copy;
context.customParam = customParam;
context.customEvent = eventType;
if (!selectorStr.length) {
selectorStr = [self.BHSelectorByEvent objectForKey:@(eventType)];
}
SEL seletor = NSSelectorFromString(selectorStr);
if (!seletor) {
selectorStr = [self.BHSelectorByEvent objectForKey:@(eventType)];
seletor = NSSelectorFromString(selectorStr);
}
NSArray<id<BHModuleProtocol>> *moduleInstances;
if (target) {
moduleInstances = @[target];
} else {
moduleInstances = [self.BHModulesByEvent objectForKey:@(eventType)];
}
//遍歷 moduleInstances 實(shí)例數(shù)組,調(diào)用performSelector:withObject:方法實(shí)現(xiàn)對(duì)應(yīng)方法調(diào)用
[moduleInstances enumerateObjectsUsingBlock:^(id<BHModuleProtocol> moduleInstance, NSUInteger idx, BOOL * _Nonnull stop) {
if ([moduleInstance respondsToSelector:seletor]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
//進(jìn)行方法調(diào)用
[moduleInstance performSelector:seletor withObject:context];
#pragma clang diagnostic pop
[[BHTimeProfiler sharedTimeProfiler] recordEventTime:[NSString stringWithFormat:@"%@ --- %@", [moduleInstance class], NSStringFromSelector(seletor)]];
}
}];
}
3、BeeHive模塊調(diào)用
通過BHServiceManager來管理已經(jīng)注冊(cè)的Protocol
注冊(cè)Protocol的方式和注冊(cè)Module方式一一對(duì)應(yīng)
.plist文件
- 設(shè)置
plist文件路徑
[BHContext shareInstance].serviceConfigName = @"BeeHive.bundle/BHService";
- 創(chuàng)建
plist文件
image.png
-
loadStaticServices方法讀取plist文件,存儲(chǔ)到字典中
#pragma mark - Private
//初始化context,加載Modules、Services
-(void)setContext:(BHContext *)context
{
_context = context;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self loadStaticServices];
[self loadStaticModules];
});
}
//加載Services
-(void)loadStaticServices
{
[BHServiceManager sharedManager].enableException = self.enableException;
[[BHServiceManager sharedManager] registerLocalServices];
}
- (void)registerLocalServices
{
NSString *serviceConfigName = [BHContext shareInstance].serviceConfigName;
//plist文件路徑
NSString *plistPath = [[NSBundle mainBundle] pathForResource:serviceConfigName ofType:@"plist"];
if (!plistPath) {
return;
}
NSArray *serviceList = [[NSArray alloc] initWithContentsOfFile:plistPath];
[self.lock lock];
//遍歷并存儲(chǔ)到allServicesDict中
for (NSDictionary *dict in serviceList) {
NSString *protocolKey = [dict objectForKey:@"service"];
NSString *protocolImplClass = [dict objectForKey:@"impl"];
if (protocolKey.length > 0 && protocolImplClass.length > 0) {
[self.allServicesDict addEntriesFromDictionary:@{protocolKey:protocolImplClass}];
}
}
[self.lock unlock];
}
動(dòng)態(tài)注冊(cè)(load)
- 在
load方法中注冊(cè)Protocol協(xié)議,通過調(diào)用BeeHive里面的registerService:service:方法完成注冊(cè)
+ (void)load
{
[[BeeHive shareInstance] registerService:@protocol(UserTrackServiceProtocol) service:[BHUserTrackViewController class]];
}
??
- (void)registerService:(Protocol *)proto service:(Class) serviceClass
{
[[BHServiceManager sharedManager] registerService:proto implClass:serviceClass];
}
Annotation注冊(cè)
//****** 1、通過BeeHiveService宏進(jìn)行Annotation標(biāo)記
BeeHiveService(HomeServiceProtocol,BHViewController)
//****** 2、宏定義
#define BeeHiveService(servicename,impl) \
class BeeHive; char * k##servicename##_service BeeHiveDATA(BeehiveServices) = "{ \""#servicename"\" : \""#impl"\"}";
//****** 3、轉(zhuǎn)換后的格式,也是將其存儲(chǔ)到特殊的段
char * kHomeServiceProtocol_service __attribute((used, section("__DATA,""BeehiveServices"" "))) = "{ \"""HomeServiceProtocol""\" : \"""BHViewController""\"}";
獲取Protocol
Protocol相比Module,可以返回Protocol實(shí)例對(duì)象
- (id)createService:(Protocol *)proto;
{
return [[BHServiceManager sharedManager] createService:proto];
}
??
- (id)createService:(Protocol *)service
{
return [self createService:service withServiceName:nil];
}
??
- (id)createService:(Protocol *)service withServiceName:(NSString *)serviceName {
return [self createService:service withServiceName:serviceName shouldCache:YES];
}
??
- (id)createService:(Protocol *)service withServiceName:(NSString *)serviceName shouldCache:(BOOL)shouldCache {
if (!serviceName.length) {
serviceName = NSStringFromProtocol(service);
}
id implInstance = nil;
//判斷protocol是否已經(jīng)注冊(cè)過
if (![self checkValidService:service]) {
if (self.enableException) {
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"%@ protocol does not been registed", NSStringFromProtocol(service)] userInfo:nil];
}
}
NSString *serviceStr = serviceName;
//如果有緩存,則直接從緩存中獲取
if (shouldCache) {
id protocolImpl = [[BHContext shareInstance] getServiceInstanceFromServiceName:serviceStr];
if (protocolImpl) {
return protocolImpl;
}
}
//獲取類后,然后響應(yīng)下層的方法
Class implClass = [self serviceImplClass:service];
if ([[implClass class] respondsToSelector:@selector(singleton)]) {
if ([[implClass class] singleton]) {
if ([[implClass class] respondsToSelector:@selector(shareInstance)])
//創(chuàng)建單例對(duì)象
implInstance = [[implClass class] shareInstance];
else
//創(chuàng)建實(shí)例對(duì)象
implInstance = [[implClass alloc] init];
if (shouldCache) {
//緩存
[[BHContext shareInstance] addServiceWithImplInstance:implInstance serviceName:serviceStr];
return implInstance;
} else {
return implInstance;
}
}
}
return [[implClass alloc] init];
}
創(chuàng)建service之前,會(huì)檢查Protocol是否注冊(cè)過
從字典中取出Protocol對(duì)應(yīng)的Class
如果實(shí)現(xiàn)了
singleton方法實(shí)現(xiàn)了
shareInstance,創(chuàng)建單例否則創(chuàng)建實(shí)例對(duì)象
將
implInstance和serviceStr緩存創(chuàng)建實(shí)例對(duì)象
serviceImplClass方法中,protocol為key,serviceImp為value存在字典中
- (Class)serviceImplClass:(Protocol *)service
{
//通過字典將 協(xié)議 和 類 綁定,其中協(xié)議作為key,serviceImp(類的名字)作為value
NSString *serviceImpl = [[self servicesDict] objectForKey:NSStringFromProtocol(service)];
if (serviceImpl.length > 0) {
return NSClassFromString(serviceImpl);
}
return nil;
}
輔助類
BHConfig:?jiǎn)卫?,維護(hù)一些動(dòng)態(tài)的環(huán)境變量,作為BHContext的補(bǔ)充BHContext:?jiǎn)卫?,?nèi)部?jī)蓚€(gè)字典屬性:modulesByName、servicesByName,用來保存上下文信息BHTimeProfiler:計(jì)算時(shí)間性能方面的BHWatchDog:新開一個(gè)線程,監(jiān)聽主線程是否堵塞


