美文网首页
Aop切面编程

Aop切面编程

作者: 一只长毛猫 | 来源:发表于2018-05-27 15:18 被阅读28次

    1 什么是切面编程
    2 KVO就是一个切面编程的例子
    3 借鉴KVO切面编程,用自己的方法实现
    4 代码实现

    切面编程概念

    这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

    KVO切面编程实例

    原理:Apple使用了isa 混写(isa - swizzling)来实现。如图


    OC基础-KVO

    关于KVO详细内容请看我的另一篇文章https://www.jianshu.com/p/c98c995bda08

    实现自己的Aop

    先了解一下OC消息转发的大致原理。
    1 动态添加 resolveInstanceMethod:
    2 重定向 forwardingTargetForSelector:
    3 方法签名后,调用forwardingTargetForSelector
    第3步,灵活性是最大的,可以改变方法的参数内容,个数,方法名字,方法接收对象等。Aop切面编程就是用的第三个。

    假设Person类,有一个实例方法sayHello(); 现在要求,每次调用sayHello()之前调用一段代码Before,sayHello之后调用一段代码after。
    1 创建子类,避免代码入侵。
    动态创建一个Person类的子类FWHook_Person ,改变person对象的isa指向FWHook_Person. 后面的步奏,都是针对FWHook_Person的
    2 把sayHello的方法实现保存在 方法alias_sayHello中
    3 替换sayHello方法实现为_objc_msgForward。使得person调用sayHello方法时,立即触发消息转发机制。
    4 替换forwardInvocation:为FWHook_forwardInvocation。在这里我们实现,我们需要做的一些具体操作


    Aop流程图

    当[person sayHello]时,实际调用[person _objc_msgForward], 触发消息转发调用 forwardInvocation的替换方法FWHook_forwardInvocation,在FWHook_forwardInvocation中依次调用before、alias_sayHello、after.

    代码实现

    1 FWHookItem对block进行代码签名

    @interface FWHookItem : NSObject
    
    @property (nonatomic, weak) id object;
    @property (nonatomic, assign) SEL selector;
    @property (nonatomic, assign) FWHookOption option;
    @property (nonatomic, strong) id block;
    @property (nonatomic, strong) NSMethodSignature *blockSignature;
    
    +(instancetype)itemWithObject:(id)object selector:(SEL)selector option:(FWHookOption)option block:(id)block;
    
    /*
     方法调用
     */
    -(void)invokeWithParams:(NSArray*)params;
    
    @end
    

    2 FWHookContainer保存FWHookItem

    @interface FWHookContainer : NSObject
    
    @property(nonatomic,readonly)NSMutableArray<FWHookItem*> *beforeArray;
    @property(nonatomic,readonly)NSMutableArray<FWHookItem*> *insteadArray;
    @property(nonatomic,readonly)NSMutableArray<FWHookItem*> *afterArray;
    
    -(void)addHookItem:(FWHookItem*)item;
    
    @end
    

    3 获取selector参数

    @interface NSInvocation (FWArguments)
    
    - (NSArray *)getParams;
    
    @end
    

    4 使用

    typedef void (^ParamsBlock)(NSArray *params);
    
    @interface NSObject (FWHook)
    
    /*
     selector : 需要监听的方法
     option : 决定 block 执行时机,在selector的之前,之后,替代。 
     block :执行的代码块 返回的params就是,selector中的参数
     */
    -(void)hookSelector:(SEL)selector withOption:(FWHookOption)option usingBlock:(ParamsBlock)block;
    +(void)hookSelector:(SEL)selector withOption:(FWHookOption)option usingBlock:(ParamsBlock)block;
    
    
    @end
    

    源码地址:https://github.com/FSilver/FWHook

    相关文章

      网友评论

          本文标题:Aop切面编程

          本文链接:https://www.haomeiwen.com/subject/yiftjftx.html