什么是面向切面编程
Aspect Oriented Programming(AOP),面向切面编程,是一个比较热门的话题。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
主要用来处理一些具有横切性质的系统性服务,如日志记录、权限管理、缓存、对象池管理等,AOP 已经成为一种非常常用的解决方案。
比如说我们在实现权限验证的时候,需要在每个业务的执行前对权限进行相应的判断,从而导致了大量的重复代码,不利于模块的复用。AOP则通过将每个业务的公共行为进行抽离,封装成一个可复用的模块,这个模块就叫做『切面』。
什么是Aspects
Aspects是一个轻量级的面向切面编程的库。它主要提供了三个切入点:before(在原始的方法前执行)/instead(替换原始的方法执行)/after(在原始的方法后执行,默认),通过Runtime消息转发实现Hook,同时这也会带来一定的负担,所以它不适合循环多次调用的方法。
Aspects扩展了NSObject类,对外提供如下两个方法:
1 2 3 4 5 6 7 8 9 10 11 |
///为指定的类的当前方法的before/instead/after切入点添加block代码 + (id)aspect_hookSelector:(SEL)selector withOptions:(AspectOptions)options usingBlock:(id)block error:(NSError **)error; ///为指定实例的当前方法的before/instead/after切入点添加block代码 - (id)aspect_hookSelector:(SEL)selector withOptions:(AspectOptions)options usingBlock:(id)block error:(NSError **)error; |
Aspects初始化工作核心部分的解析
aspect_add方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
static id aspect_add(id self, SEL selector, AspectOptions options, id block, NSError **error) { NSCParameterAssert(self); NSCParameterAssert(selector); NSCParameterAssert(block); //声明AspectIdentifier实例 __block AspectIdentifier *identifier = nil; aspect_performLocked(^{ //判断当前XX方法是否允许被Hook,1."retain"、"release"、"autorelease"、"forwardInvocation"这几个方法是不被允许的,所谓的黑名单。2.如果方法是dealloc,则他的切入点必须是Before。3.判断当前实例对象和类对象是否能响应方法4.是否是类对象,如果是则判断继承体系中方法是否已经被Hook,而实例则不用。 if (aspect_isSelectorAllowedAndTrack(self, selector, options, error)) { //获得当前aspects__XX方法的AspectsContainer容器 AspectsContainer *aspectContainer = aspect_getContainerForObject(self, selector); //初始化AspectIdentifier变量,方法内部通过toll-free bridged获取Block方法签名,并判断其兼容性 identifier = [AspectIdentifier identifierWithSelector:selector object:self options:options block:block error:error]; if (identifier) { //通过options选项分别添加到容器中的beforeAspects,insteadAspects,afterAspects这三个数组 [aspectContainer addAspect:identifier withOptions:options]; //HookSelector的过程和HookClass的过程 aspect_prepareClassAndHookSelector(self, selector, error); } } }); return identifier; } |
HookClass过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
static Class aspect_hookClass(NSObject *self, NSError **error) { NSCParameterAssert(self); Class statedClass = self.class; Class baseClass = object_getClass(self); NSString *className = NSStringFromClass(baseClass); // 如果类名有_Aspects_前缀,说明Class已被Hook if ([className hasSuffix:AspectsSubclassSuffix]) { return ayon-v">hasSuffix:AspectsSubclassSuffix]) { return 是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
主要用来处理一些具有横切性质的系统性服务,如日志记录、权限管理、缓存、对象池管理等,AOP 已经成为一种非常常用的解决方案。 比如说我们在实现权限验证的时候,需要在每个业务的执行前对权限进行相应的判断,从而导致了大量的重复代码,不利于模块的复用。AOP则通过将每个业务的公共行为进行抽离,封装成一个可复用的模块,这个模块就叫做『切面』。 什么是AspectsAspects是一个轻量级的面向切面编程的库。它主要提供了三个切入点:before(在原始的方法前执行)/instead(替换原始的方法执行)/after(在原始的方法后执行,默认),通过Runtime消息转发实现Hook,同时这也会带来一定的负担,所以它不适合循环多次调用的方法。 Aspects扩展了NSObject类,对外提供如下两个方法:
Aspects初始化工作核心部分的解析aspect_add方法:
HookClass过程:
|