程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Objective-C 下的 AOP 編程

Objective-C 下的 AOP 編程

編輯:關於C語言

Objective-C 下的 AOP 編程


Objective-C 下的 AOP 編程

概念

在軟件業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,是函數式編程的一種衍生范型。通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。主要的功能是:日志記錄,性能統計,安全控制,事務處理,異常處理等等。主要的意圖是:將日志記錄,性能統計,安全控制,事務處理,異常處理等代碼從業務邏輯代碼中劃分出來,通過對這些行為的分離,我們希望可以將它們獨立到非指導業務邏輯的方法中,進而改變這些行為的時候不影響業務邏輯的代碼。

運用

這裡舉個例子,我們有個方法sumA:andB:, 用來返回ab之和的一個字串,我們在這個方法前和方法後都增加個一段代碼

在運行方法前我們把參數改成2和3, 當然這裡是演示用,實際用的時候別改參數,不然其他同事真的要罵人了在運行方法後我們輸出傳入的參數和返回值
- (void)clickTestAop:(id)sender
{
    AopTestM *test = [[AopTestM alloc] init];
    NSLog(@"run1");
    [test sumA:1 andB:2];
    
    NSString *before = [XYAOP interceptClass:[AopTestM class] beforeExecutingSelector:@selector(sumA:andB:) usingBlock:^(NSInvocation *invocation) {
        int a = 3;
        int b = 4;
        
        [invocation setArgument:&a atIndex:2];
        [invocation setArgument:&b atIndex:3];
        
        NSLog(@"berore fun. a = %d, b = %d", a , b);
    }];
    
    NSString *after =  [XYAOP interceptClass:[AopTestM class] afterExecutingSelector:@selector(sumA:andB:) usingBlock:^(NSInvocation *invocation) {
        int a;
        int b;
        NSString *str;
        
        [invocation getArgument:&a atIndex:2];
        [invocation getArgument:&b atIndex:3];
        [invocation getReturnValue:&str];
        
        NSLog(@"berore fun. a = %d, b = %d, sum = %@", a , b, str);
    }];
    
    NSLog(@"run2");
    [test sumA:1 andB:2];
    
    [XYAOP removeInterceptorWithIdentifier:before];
    [XYAOP removeInterceptorWithIdentifier:after];
    
    NSLog(@"run3");
    [test sumA:1 andB:2];
} 

- (NSString *)sumA:(int)a andB:(int)b
{
    int value = a + b;
    NSString *str = [NSString stringWithFormat:@"fun running. sum : %d", value];
    NSLog(@"%@", str);
    
    return str;
}


我們執行這段代碼的時候,大伙猜猜結果是啥.結果如下

2014-10-28 22:52:47.215 JoinShow[3751:79389] run1
2014-10-28 22:52:52.744 JoinShow[3751:79389] fun running. sum : 3
2014-10-28 22:52:52.745 JoinShow[3751:79389] run2
2014-10-28 22:52:52.745 JoinShow[3751:79389] berore fun. a = 3, b = 4
2014-10-28 22:52:52.745 JoinShow[3751:79389] fun running. sum : 7
2014-10-28 22:52:52.745 JoinShow[3751:79389] berore fun. a = 3, b = 4, sum = fun running. sum : 7
2014-10-28 22:52:52.746 JoinShow[3751:79389] run3
2014-10-28 22:52:52.746 JoinShow[3751:79389] fun running. sum : 3

實現原理

用Objective-C強大的runtime.

我們知道當給一個對象發送一個方法的時候, 如果當前類和父類都沒實現該方法的時候就會走轉發流程

動態方法解析 -> 快速消息轉發 -> 標准消息轉發

迷茫的同學請搜 "Objective-C 消息轉發".

了解了消息轉發,那麼我們aop的思路就來了,我們是先干掉原本的方法funa,這樣當給對象發送方法的時候就會走轉發流程,我們再hook了對象的快速消息轉發方法,把實現funa的對象指成我們的aop對象, 最後在aop對象的標准消息轉發裡執行before instead after方法.

具體的代碼歡迎大伙去github下載, 記得給咱點個star

link https://github.com/uxyheaven/XYQuickDevelop

在代碼裡搜 XYAOP.h

相關一些方法介紹

介紹一些用到的runtime方法

// 給 cls 添加一個新方法
BOOL class_addMethod (
   Class cls,
   SEL name,
   IMP imp,
   const char *types
);

// 替換 cls 裡的一個方法的實現
IMP class_replaceMethod (
   Class cls,
   SEL name,
   IMP imp,
   const char *types
);

// 返回 cls 的指定方法
Method class_getInstanceMethod (
   Class cls,
   SEL name
);

// 設置一個方法的實現
IMP method_setImplementation (
   Method m,
   IMP imp
);

// 返回 cls 裡的 name 方法的實現
IMP class_getMethodImplementation (
   Class cls,
   SEL name
);


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved