美文网首页
Aspects源码详解(一)

Aspects源码详解(一)

作者: Jimm_鱼 | 来源:发表于2018-10-21 19:06 被阅读6次

    AOP(Aspect Oriented Programming)面向切片编程

    • AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。

    iOS 如何如何实现面向切片编程

    • AOP一般都是需要有一个拦截器,然后在每一个切片运行之前和运行之后(或者任何你希望的地方),通过调用拦截器的方法来把这个jointpoint扔到外面,在外面获得这个jointpoint的时候,执行相应的代码。
    • 在iOS开发领域,objective-C的runtime有提供了一系列的方法,能够让我们拦截到某个方法的调用,来实现拦截器的功能,这种手段我们称为Method Swizzling。Aspects通过这个手段实现了针对某个类和某个实例中方法的拦截。

    使用场景:

    • 统一处理逻辑
    • 在不改变源码的情况下,插入源码
    • 当我们执行某种方法时候,对方法进行安全检查 (例如,NSArray的数组越界问题)
    • 对某些操作进行日志记录
    • 对购物车进行交互时候,根据用户的操作,触发建议或者提示

    源码解析:

    AspectOptions

    typedef NS_OPTIONS(NSUInteger, AspectOptions) {
        AspectPositionAfter   = 0,/// Called after the original implementation (default)
        AspectPositionInstead = 1,/// Will replace the original implementation.
        AspectPositionBefore  = 2,/// Called before the original implementation.
        AspectOptionAutomaticRemoval = 1 << 3 /// Will remove the hook after the first execution.
    };
    

    这是一个枚举,定义了切片的调用时机

    公共接口

    #pragma mark - Public Aspects API
    + (id<AspectToken>)aspect_hookSelector:(SEL)selector
                          withOptions:(AspectOptions)options
                           usingBlock:(id)block
                                error:(NSError **)error {
        return aspect_add((id)self, selector, options, block, error);
    }
    
    /// @return A token which allows to later deregister the aspect.
    - (id<AspectToken>)aspect_hookSelector:(SEL)selector
                          withOptions:(AspectOptions)options
                           usingBlock:(id)block
                                error:(NSError **)error {
        return aspect_add(self, selector, options, block, error);
    }
    

    Aspects是NSObject的分类 @interface NSObject (Aspects),然后提供了实例方法和类方法

    • 参数
      1. selector: 要被hook的selector,这是一个SEL类型
      2. options: 切面的执行时机,也就是设置第三个参数block的调用时
      3. block: 切面 (block 是带有自动变量值的匿名函数,其实block的实质也是Objective-C的对象,所以这里能用id来引用,具体详细解析可以参考《Objective-C高级编程》这一本书)
      4. error: hook过程中出现的错误

    aspect_add

    static id aspect_add(id self, SEL selector, AspectOptions options, id block, NSError **error) {
        NSCParameterAssert(self);
        NSCParameterAssert(selector);
        NSCParameterAssert(block);
    
        __block AspectIdentifier *identifier = nil;
        aspect_performLocked(^{
            if (aspect_isSelectorAllowedAndTrack(self, selector, options, error)) {
                AspectsContainer *aspectContainer = aspect_getContainerForObject(self, selector);
                identifier = [AspectIdentifier identifierWithSelector:selector object:self options:options block:block error:error];
                if (identifier) {
                    [aspectContainer addAspect:identifier withOptions:options];
    
                    // Modify the class to allow message interception.
                    aspect_prepareClassAndHookSelector(self, selector, error);
                }
            }
        });
        return identifier;
    }
    
    static void aspect_performLocked(dispatch_block_t block) {
        static OSSpinLock aspect_lock = OS_SPINLOCK_INIT;
        OSSpinLockLock(&aspect_lock);
        block();
        OSSpinLockUnlock(&aspect_lock);
    }
    

    下个系列的文章后面待续

    相关文章

      网友评论

          本文标题:Aspects源码详解(一)

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