1. 开源库基本信息:

开源地址


2. 源码解析

BeeHive 整体结构

BeeHive 整个模块由上图几个模块构成:

  • BeeHive:

BeeHive是BeeHive的核心接口类,它主要用于注册Module,注册Service,查找符合某个协议的Service,以及触发自定义事件。
它在setContext的时候会加载一系列的静态服务和模块

  • BHAppDelegate:

BHAppDelegate负责转发系统消息的代理,项目中的代理需要继承这个方法。

  • BHContext:

BHContext用于存放公共数据的上下文,某个服务的对应的实现类对象也会缓存到这个地方。

  • BHRouter:
    BHRouter是BeeHive的路由,支持查找服务,跳转页面,注册服务。是基于URL的格式:目前支持的协议如下:
    //url - >  com.alibaba.beehive://call.service.beehive/pathComponentKey.protocolName.selector/...?params={}(value url encode)
    //url - > com.alibaba.beehive://register.beehive/pathComponentKey.protocolName/...?params={}(value url encode)
    //url - > com.alibaba.beehive://jump.vc.beehive/pathComponentKey.protocolName.push(modal)/...?params={}(value url encode)#push
    //params -> {pathComponentKey:{paramName:paramValue,...},...}
  • BHModuleManager:

BHModuleManager 主要负责管理模块和分发事件

  • BHServiceManager:

BHModuleManager 负责注册,查找,定位,删除服务

不论是服务还是模块,BeeHive都提供了三种不同的注册形式:静态plist,动态注册,annotation。

个人觉得可以将事件从BHModuleManager中独立出来会显得比较清晰,并且将路由功能也通过BeeHive暴露接口,这样用户需要什么功能都可以直接调用BeeHive接口。

也就是说整个项目以BeeHive为中心,BHAppDelegate持有BeeHive,并向BeeHive注入系统事件,BHContext向BeeHive注入上下文,BeeHive作为对外的门面,向外界暴露模块,服务,事件,路由管理功能,而模块功能由BHModuleManager实际管理,服务功能由BHServiceManager具体管理,事件由BHEventManager管理,路由由BHRouter管理。大体如下图所示:

模块管理器 BHModuleManager

BHModuleManager 主要负责两大类任务:

1. 通过模块的静态加载,动态注册添加模块
2. 注册模块事件
模块添加移除

模块动态注册

模块注册是通过registerDynamicModule函数注册的,参数是模块的Class。

- (void)registerDynamicModule:(Class)moduleClass {
[self registerDynamicModule:moduleClass shouldTriggerInitEvent:NO];
}
- (void)registerDynamicModule:(Class)moduleClass
shouldTriggerInitEvent:(BOOL)shouldTriggerInitEvent {
[self addModuleFromObject:moduleClass shouldTriggerInitEvent:shouldTriggerInitEvent];
}
- (void)addModuleFromObject:(id)object
shouldTriggerInitEvent:(BOOL)shouldTriggerInitEvent {

Class class;
NSString *moduleName = nil;

if (!object) return;

//使用传入的参数初始化关键参数
class = object;
moduleName = NSStringFromClass(class);

//遍历已经注册的Module查看是否已经添加过
__block BOOL flag = YES;
[self.BHModules enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:class]) {
flag = NO;
*stop = YES;
}
}];

// 如果已经添加过则直接返回
if (!flag) return;

if ([class conformsToProtocol:@protocol(BHModuleProtocol)]) {
NSMutableDictionary *moduleInfo = [NSMutableDictionary dictionary];
BOOL responseBasicLevel = [class instancesRespondToSelector:@selector(basicModuleLevel)];
int levelInt = 1;
if (responseBasicLevel) {
levelInt = 0;
}
//填充Module基本信息
[moduleInfo setObject:@(levelInt) forKey:kModuleInfoLevelKey];
if (moduleName) {
[moduleInfo setObject:moduleName forKey:kModuleInfoNameKey];
}
//添加到模块基本信息里面
[self.BHModuleInfos addObject:moduleInfo];
//将模块实例添加到BHModules
id<BHModuleProtocol> moduleInstance = [[class alloc] init];
[self.BHModules addObject:moduleInstance];
[moduleInfo setObject:@(YES) forKey:kModuleInfoHasInstantiatedKey];

//模块排序:先根据基本模块等级 再根据模块优先级
[self.BHModules sortUsingComparator:^NSComparisonResult(id<BHModuleProtocol> moduleInstance1, id<BHModuleProtocol> moduleInstance2) {
NSNumber *module1Level = @(BHModuleNormal);
NSNumber *module2Level = @(BHModuleNormal);
if ([moduleInstance1 respondsToSelector:@selector(basicModuleLevel)]) {
module1Level = @(BHModuleBasic);
}
if ([moduleInstance2 respondsToSelector:@selector(basicModuleLevel)]) {
module2Level = @(BHModuleBasic);
}
if (module1Level.integerValue != module2Level.integerValue) {
return module1Level.integerValue > module2Level.integerValue;
} else {
NSInteger module1Priority = 0;
NSInteger module2Priority = 0;
if ([moduleInstance1 respondsToSelector:@selector(modulePriority)]) {
module1Priority = [moduleInstance1 modulePriority];
}
if ([moduleInstance2 respondsToSelector:@selector(modulePriority)]) {
module2Priority = [moduleInstance2 modulePriority];
}
return module1Priority < module2Priority;
}
}];
//注册模块监听事件
[self registerEventsByModuleInstance:moduleInstance];

//触发基本的事件
if (shouldTriggerInitEvent) {
//触发启动
[self handleModuleEvent:BHMSetupEvent forTarget:moduleInstance withSeletorStr:nil andCustomParam:nil];
//触发初始化
[self handleModulesInitEventForTarget:moduleInstance withCustomParam:nil];
dispatch_async(dispatch_get_main_queue(), ^{
//触发闪现
[self handleModuleEvent:BHMSplashEvent forTarget:moduleInstance withSeletorStr:nil andCustomParam:nil];
});
}
}
}

模块注册涉及到两个数组BHModuleInfos 以及 BHModules一个用于存放模块的信息,一个用于存放模块,模块信息包括:模块名(kModuleInfoNameKey),模块等级(kModuleInfoLevelKey),模块是否有实例对象(kModuleInfoHasInstantiatedKey)。每个模块都必须遵循BHModuleProtocol协议。在每次添加的时候都会按照模块level以及模块优先级进行排序。

然后在通过registerEventsByModuleInstance来注册消息事件的监听,如果shouldTriggerInitEvent为YES那么就会触发BHMSetupEvent,BHMInitEvent,BHMSplashEvent事件。

模块移除

- (void)unRegisterDynamicModule:(Class)moduleClass {
if (!moduleClass) {
return;
}
[self.BHModuleInfos filterUsingPredicate:[NSPredicate predicateWithFormat:@"%@!=%@", kModuleInfoNameKey, NSStringFromClass(moduleClass)]];
__block NSInteger index = -1;
//查找要移除的模块
[self.BHModules enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:moduleClass]) {
index = idx;
*stop = YES;
}
}];
//移除模块
if (index >= 0) {
[self.BHModules removeObjectAtIndex:index];
}
//遍历每个事件,有关于当前实例的就从某个事件的监听列表中移除
[self.BHModulesByEvent enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, NSMutableArray<id<BHModuleProtocol>> * _Nonnull obj, BOOL * _Nonnull stop) {
__block NSInteger index = -1;
[obj enumerateObjectsUsingBlock:^(id<BHModuleProtocol> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:moduleClass]) {
index = idx;
*stop = NO;
}
}];
//从事件中移除
if (index >= 0) {
[obj removeObjectAtIndex:index];
}
}];
}

模块移除也遵循上面的步骤,首先是会从BHModules中移除,而后再从事件中移除,后者会放在后面介绍事件的时候进行详细介绍。

全部模块注册

全部模块注册的任务是对模块信息中没有实例化的模块进行实例化后添加到self.BHModules,并对这些模块同一监听系统事件。

- (void)registedAllModules {

[self.BHModuleInfos sortUsingComparator:^NSComparisonResult(NSDictionary *module1, NSDictionary *module2) {
NSNumber *module1Level = (NSNumber *)[module1 objectForKey:kModuleInfoLevelKey];
NSNumber *module2Level = (NSNumber *)[module2 objectForKey:kModuleInfoLevelKey];
if (module1Level.integerValue != module2Level.integerValue) {
return module1Level.integerValue > module2Level.integerValue;
} else {
NSNumber *module1Priority = (NSNumber *)[module1 objectForKey:kModuleInfoPriorityKey];
NSNumber *module2Priority = (NSNumber *)[module2 objectForKey:kModuleInfoPriorityKey];
return module1Priority.integerValue < module2Priority.integerValue;
}
}];
NSMutableArray *tmpArray = [NSMutableArray array];
//对于模块信息中没有实例化的模块进行实例化后添加到self.BHModules,并对这些模块同一监听系统事件
[self.BHModuleInfos enumerateObjectsUsingBlock:^(NSDictionary *module, NSUInteger idx, BOOL * _Nonnull stop) {
NSString *classStr = [module objectForKey:kModuleInfoNameKey];
Class moduleClass = NSClassFromString(classStr);
BOOL hasInstantiated = ((NSNumber *)[module objectForKey:kModuleInfoHasInstantiatedKey]).boolValue;
if (NSStringFromClass(moduleClass) && !hasInstantiated) {
id<BHModuleProtocol> moduleInstance = [[moduleClass alloc] init];
[tmpArray addObject:moduleInstance];
}
}];

[self.BHModules addObjectsFromArray:tmpArray];
[self registerAllSystemEvents];
}

那么哪些模块是不会在注册的时候实例化呢?其实我们刚刚看到了,注册方法中有个Dynamic关键字表示动态注册,相对的BeeHive支持从plist文件中静态注册,这些静态注册的模块需要调用registedAllModules进行实例化,并注册事件。

模块静态注册

- (void)loadLocalModules {

//从plist中加载Module
NSString *plistPath = [[NSBundle mainBundle] pathForResource:[BHContext shareInstance].moduleConfigName ofType:@"plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
return;
}
NSDictionary *moduleList = [[NSDictionary alloc] initWithContentsOfFile:plistPath];

NSArray<NSDictionary *> *modulesArray = [moduleList objectForKey:kModuleArrayKey];
NSMutableDictionary<NSString *, NSNumber *> *moduleInfoByClass = @{}.mutableCopy;
//构建出一个key --> XXXXClass value--> @(1) 便于查询,其实这里感觉BHModuleInfos设计不是很合理,为什么不用Dictionary
[self.BHModuleInfos enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[moduleInfoByClass setObject:@1 forKey:[obj objectForKey:kModuleInfoNameKey]]; //key --> XXXXClass value--> @(1)
}];
//没有的话添加到self.BHModuleInfos
[modulesArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (!moduleInfoByClass[[obj objectForKey:kModuleInfoNameKey]]) {
[self.BHModuleInfos addObject:obj];
}
}];
}
模块事件

BeeHive的事件分成两类:系统事件以及自定义事件,自定义事件的值规定大于1000.
整个实现涉及到两个字典:BHSelectorByEventBHSelectorByEvent,两个字典的key都是EventType,可以通过EventType在BHSelectorByEvent找到响应selector,通过BHSelectorByEvent能够找到对应的模块。我们知道事件的三要素要明确:哪个实例? 监听哪个事件? 用哪个selector处理*,这些都可以通过这两个字典串起来。

事件注册:

系统事件是默认添加的,但是注册是需要手动注册的,在注册模块的时候可以选择默认注册BHMSetupEvent,BHMInitEvent,BHMSplashEvent事件。

- (NSMutableDictionary<NSNumber *, NSString *> *)BHSelectorByEvent {
if (!_BHSelectorByEvent) {
_BHSelectorByEvent = @{
@(BHMSetupEvent):kSetupSelector,
@(BHMInitEvent):kInitSelector,
@(BHMTearDownEvent):kTearDownSelector,
@(BHMSplashEvent):kSplashSeletor,
@(BHMWillResignActiveEvent):kWillResignActiveSelector,
@(BHMDidEnterBackgroundEvent):kDidEnterBackgroundSelector,
@(BHMWillEnterForegroundEvent):kWillEnterForegroundSelector,
@(BHMDidBecomeActiveEvent):kDidBecomeActiveSelector,
@(BHMWillTerminateEvent):kWillTerminateSelector,
@(BHMUnmountEvent):kUnmountEventSelector,
@(BHMOpenURLEvent):kOpenURLSelector,
@(BHMDidReceiveMemoryWarningEvent):kDidReceiveMemoryWarningSelector,
@(BHMDidReceiveRemoteNotificationEvent):kDidReceiveRemoteNotificationsSelector,
@(BHMWillPresentNotificationEvent):kWillPresentNotificationSelector,
@(BHMDidReceiveNotificationResponseEvent):kDidReceiveNotificationResponseSelector,
@(BHMDidFailToRegisterForRemoteNotificationsEvent):kFailToRegisterForRemoteNotificationsSelector,
@(BHMDidRegisterForRemoteNotificationsEvent):kDidRegisterForRemoteNotificationsSelector,
@(BHMDidReceiveLocalNotificationEvent):kDidReceiveLocalNotificationsSelector,
@(BHMWillContinueUserActivityEvent):kWillContinueUserActivitySelector,
@(BHMContinueUserActivityEvent):kContinueUserActivitySelector,
@(BHMDidFailToContinueUserActivityEvent):kFailToContinueUserActivitySelector,
@(BHMDidUpdateUserActivityEvent):kDidUpdateContinueUserActivitySelector,
@(BHMQuickActionEvent):kQuickActionSelector,
@(BHMHandleWatchKitExtensionRequestEvent):kHandleWatchKitExtensionRequestSelector,
@(BHMDidCustomEvent):kAppCustomSelector,
}.mutableCopy;
}
return _BHSelectorByEvent;
}

我们先来看下事件的注册方法:

首先会做一些预先判断:要注册的实例是否能够响应指定的selector,如果不能就不注册了,如果可以响应那么将eventType为key,selectorStr为value添加到BHSelectorByEvent,然后在查看BHModulesByEvent对应的eventType下面是否添加了当前的实例。添加后再按照modelLevel以及priority对实例进行排序,保证BHModulesByEvent中每个事件的实例列表是按照优先级排序的,优先级高的优先收到事件。

- (void)registerEvent:(NSInteger)eventType
withModuleInstance:(id)moduleInstance
andSelectorStr:(NSString *)selectorStr {

//判断当前实例是否能够响应selector
SEL selector = NSSelectorFromString(selectorStr);
if (!selector || ![moduleInstance respondsToSelector:selector]) return;

//添加到BHSelectorByEvent key-->eventTypeNumber value selectorStr
NSNumber *eventTypeNumber = @(eventType);
if (!self.BHSelectorByEvent[eventTypeNumber]) {
[self.BHSelectorByEvent setObject:selectorStr forKey:eventTypeNumber];
}
//添加到事件实例上
if (!self.BHModulesByEvent[eventTypeNumber]) {
[self.BHModulesByEvent setObject:@[].mutableCopy forKey:eventTypeNumber];
}
//拿到module
NSMutableArray *eventModules = [self.BHModulesByEvent objectForKey:eventTypeNumber];
//不包含的情况下添加到eventModules,并排序
if (![eventModules containsObject:moduleInstance]) {
[eventModules addObject:moduleInstance];
[eventModules sortUsingComparator:^NSComparisonResult(id<BHModuleProtocol> moduleInstance1, id<BHModuleProtocol> moduleInstance2) {
NSNumber *module1Level = @(BHModuleNormal);
NSNumber *module2Level = @(BHModuleNormal);
if ([moduleInstance1 respondsToSelector:@selector(basicModuleLevel)]) {
module1Level = @(BHModuleBasic);
}
if ([moduleInstance2 respondsToSelector:@selector(basicModuleLevel)]) {
module2Level = @(BHModuleBasic);
}
if (module1Level.integerValue != module2Level.integerValue) {
return module1Level.integerValue > module2Level.integerValue;
} else {
NSInteger module1Priority = 0;
NSInteger module2Priority = 0;
if ([moduleInstance1 respondsToSelector:@selector(modulePriority)]) {
module1Priority = [moduleInstance1 modulePriority];
}
if ([moduleInstance2 respondsToSelector:@selector(modulePriority)]) {
module2Priority = [moduleInstance2 modulePriority];
}
return module1Priority < module2Priority;
}
}];
}
}

事件触发

- (void)triggerEvent:(NSInteger)eventType
withCustomParam:(NSDictionary *)customParam {
[self handleModuleEvent:eventType forTarget:nil withCustomParam:customParam];
}
- (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;
//首先尝试使用传入的selectorStr来处理,如果不行都去BHSelectorByEvent里面去获取对应的selector
if (!selectorStr.length) {
selectorStr = [self.BHSelectorByEvent objectForKey:@(eventType)];
}
SEL seletor = NSSelectorFromString(selectorStr);
if (!seletor) {
selectorStr = [self.BHSelectorByEvent objectForKey:@(eventType)];
seletor = NSSelectorFromString(selectorStr);
}

//如果target有传入特定的,那么直接触发特定实例中的方法就好,否则触发能够响应当前事件的所有实例的selector方法
NSArray<id<BHModuleProtocol>> *moduleInstances;
if (target) {
moduleInstances = @[target];
} else {
moduleInstances = [self.BHModulesByEvent objectForKey:@(eventType)];
}
[moduleInstances enumerateObjectsUsingBlock:^(id<BHModuleProtocol> moduleInstance, NSUInteger idx, BOOL * _Nonnull stop) {
if ([moduleInstance respondsToSelector:seletor]) {
//通过performSelector触发方法
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[moduleInstance performSelector:seletor withObject:context];
#pragma clang diagnostic pop
//记录时间
[[BHTimeProfiler sharedTimeProfiler] recordEventTime:[NSString stringWithFormat:@"%@ --- %@", [moduleInstance class], NSStringFromSelector(seletor)]];
}
}];
}

事件触发实际上是通过performSelector来完成的,它需要知道要触发哪个实例的哪个事件,介绍了上面的注册流程后就可以很清楚得了解到整个事件的组织结构,那么事件的触发就是通过上面介绍的两个字典,找到事件的响应方法,以及需要触发哪些实例的对应方法了。BeeHive将模块初始化以及模块销毁独立开来是因为这两个事件有特殊之处,模块初始化有些模块是支持异步的,有些则是同步的,模块销毁的特别之处在于要按照优先级从低到高销毁。

服务管理器 BHServiceManager

在BeeHive中另一个比较重要的就是Servic了,它类似于一个提供某个处理的接口,BHServiceManager负责服务的注册,服务的移除,服务的搜索,同样BHServiceManager也提供了动态和静态注册服务的两种方式,BeeHive的服务实际上是Protocal - Class(Instance) 模式,Protocal提供了服务能够提供哪些服务的外在接口协议,而Class(Instance) 实际上则是这些服务的真正提供实例。

服务添加,移除,定位

服务动态注册

这没啥好说的一看就懂:

- (void)registerService:(Protocol *)service implClass:(Class)implClass {

NSParameterAssert(service != nil);
NSParameterAssert(implClass != nil);
//添加前判断
if (![implClass conformsToProtocol:service]) {
if (self.enableException) {
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"%@ module does not comply with %@ protocol", NSStringFromClass(implClass), NSStringFromProtocol(service)] userInfo:nil];
}
return;
}

if ([self checkValidService:service]) {
if (self.enableException) {
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"%@ protocol has been registed", NSStringFromProtocol(service)] userInfo:nil];
}
return;
}

NSString *key = NSStringFromProtocol(service);
NSString *value = NSStringFromClass(implClass);

//加入BHModuleManager key 为 Protocol value 为 实现类Class
if (key.length > 0 && value.length > 0) {
[self.lock lock];
[self.allServicesDict addEntriesFromDictionary:@{key:value}];
[self.lock unlock];
}
}

服务静态注册

还是不说哼哼哈哈^V^

- (void)registerLocalServices {

NSString *serviceConfigName = [BHContext shareInstance].serviceConfigName;
NSString *plistPath = [[NSBundle mainBundle] pathForResource:serviceConfigName ofType:@"plist"];
if (!plistPath) return;

NSArray *serviceList = [[NSArray alloc] initWithContentsOfFile:plistPath];

[self.lock lock];
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];
}

服务定位

- (id)createService:(Protocol *)service withServiceName:(NSString *)serviceName shouldCache:(BOOL)shouldCache/*是否从缓存中找*/ {
if (!serviceName.length) {
serviceName = NSStringFromProtocol(service);
}
id implInstance = nil;

//没有对应的实现
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;
//是否从缓存中查找,如果允许的话则从BHContext中找,找到直接返回
if (shouldCache) {
id protocolImpl = [[BHContext shareInstance] getServiceInstanceFromServiceName:serviceStr];
if (protocolImpl) {
return protocolImpl;
}
}

//如果没有在BHContext中则从serviceImplClass找
Class implClass = [self serviceImplClass:service];

if ([[implClass class] respondsToSelector:@selector(singleton)]) {
//是否是单例如果是单例则通过shareInstance创建对象,否则通过alloc创建
if ([[implClass class] singleton]) {

if ([[implClass class] respondsToSelector:@selector(shareInstance)])
implInstance = [[implClass class] shareInstance];
else
implInstance = [[implClass alloc] init];
//如果shouldCache 则添加到BHContext
if (shouldCache) {
[[BHContext shareInstance] addServiceWithImplInstance:implInstance serviceName:serviceStr];
return implInstance;
} else {
return implInstance;
}
}
}
return [[implClass alloc] init];
}

关于createService这个方法名起得个人觉得不是很好,刚看到这个方法名的时候我的第一印象是:服务不是通过regist方法注册了吗,为什么需要create,实际上这只是通过服务协议来找到服务提供对象而已,个人建议可以叫做:

- (id)serviceConfirmToProtocol:(Protocol *)service withServiceName:(NSString *)serviceName shouldCache:(BOOL)shouldCache;

这里有一个需要注意的是我们这里返回的是提供服务的实例,而我们注册的提供服务的Class,为了避免每次都根据Class创建实例 ,BHContext 中有提供对应的缓存存储在[BHContext shareInstance].servicesByName中,而我们注册的服务存储在serviceImplClass中,所以每次我们要做的就是通过Protocal从先从[BHContext shareInstance].servicesByName中找,如果有之前已经缓存的实例的话就不需要重新创建了,直接返回就可以了,如果没有那么从serviceImplClass中找到对应的class,然后初始化出实例,然后添加到[BHContext shareInstance].servicesByName中缓存。

3.Annotation 注解

这是我看BeeHive眼前一亮的一块代码,本来想将这块内容放到服务和模块注册地方来介绍的,因为BeeHive注解主要用于注册模块和服务,之所以单独成一块来介绍主要是它有一定的通用性。

我们就开始看这块内容:

注册模块的时候使用的宏定义

#define BeeHiveMod(name) \
class BeeHive; char * k##name##_mod BeeHiveDATA(BeehiveMods) = ""#name"";

注册服务时候使用的宏定义:

#define BeeHiveService(servicename,impl) \
class BeeHive; char * k##servicename##_service BeeHiveDATA(BeehiveServices) = "{ \""#servicename"\" : \""#impl"\"}";

在项目中可以这样使用:

@BeeHiveMod(ShopModule)
@interface ShopModule() <BHModuleProtocol>
@end
@BeeHiveService(HomeServiceProtocol,BHViewController)
@interface BHViewController ()<HomeServiceProtocol>

@end

我们专注来看BeeHiveMod:

#define BeeHiveMod(name) \
class BeeHive; char * k##name##_mod BeeHiveDATA(BeehiveMods) = ""#name"";

@BeeHiveMod(ShopModule) 替换后会变成:

class BeeHive; char * kShopModule_mod BeeHiveDATA(BeehiveMods) = ""ShopModule"";

再来看下:BeeHiveDATA

#define BeeHiveDATA(sectname) __attribute((used, section("__DATA,"#sectname" ")))

替换后变成:

@class BeeHive; char * kShopModule_mod __attribute((used, section("__DATA,""BeehiveMods"" "))) = """ShopModule""";

去掉__attribute的属性,相当于:

@class BeeHive; char * kShopModule_mod = """ShopModule""";

这里最重要的关键字是__attribute,由于kShopModule_mod字符串没有使用到,在Release包的时候会被优化掉所以需要使用used来避免被编译器优化,section用于指定kShopModule_mod存放的位置,section(“__DATA,””BeehiveMods”” “)表示,将kShopModule_mod存储在__DATA数据段里面的”BeehiveMods”section中。

那如何读取到这些字段呢?我们看下BHAnnotation类,我们先看下initProphet,

__attribute__((constructor))
void initProphet() {
_dyld_register_func_for_add_image(dyld_callback);
}

它用编译标记__attribute__((constructor))进行标记,****attribute((constructor))**** 的用法大家可以看下:

attribute((constructor))是在main函数之前,执行一个函数,也就是initProphet会在编译之前执行,_dyld_register_func_for_add_image(dyld_callback);回来镜像加载后调用dyld_callback。在这里面可以对加载完的镜像文件进行处理,读取出我们写到指定Session中的数据。

NSArray<NSString *>* BHReadConfiguration(char *sectionName,const struct mach_header *mhp) {
NSMutableArray *configs = [NSMutableArray array];
unsigned long size = 0;
#ifndef __LP64__
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*);
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;
}

BHReadConfiguration 用于从__DATA中读取指定session下的数据。

static void dyld_callback(const struct mach_header *mhp, intptr_t vmaddr_slide) {
NSArray *mods = BHReadConfiguration(BeehiveModSectName, mhp);
for (NSString *modName in mods) {
Class cls;
if (modName) {
cls = NSClassFromString(modName);
if (cls) {
[[BHModuleManager sharedManager] registerDynamicModule:cls];
}
}
}
//register services
NSArray<NSString *> *services = BHReadConfiguration(BeehiveServiceSectName,mhp);
for (NSString *map in services) {
NSData *jsonData = [map dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
id json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if (!error) {
if ([json isKindOfClass:[NSDictionary class]] && [json allKeys].count) {
NSString *protocol = [json allKeys][0];
NSString *clsName = [json allValues][0];
if (protocol && clsName) {
[[BHServiceManager sharedManager] registerService:NSProtocolFromString(protocol) implClass:NSClassFromString(clsName)];
}
}
}
}
}

也就是在镜像文件加载完毕后,通过BHReadConfiguration将上面注解方式添加的字符串读取出来,并使用这些数据进行注册服务和模块。

4.较好的文章推荐

Contents
  1. 1. 1. 开源库基本信息:
  2. 2. 2. 源码解析
    1. 2.1. BeeHive 整体结构
    2. 2.2. 模块管理器 BHModuleManager
      1. 2.2.1. 模块添加移除
      2. 2.2.2. 模块事件
    3. 2.3. 服务管理器 BHServiceManager
      1. 2.3.1. 服务添加,移除,定位
  3. 3. 3.Annotation 注解
  4. 4. 4.较好的文章推荐