MUWork--一个基于Objective-c的AOP开发框架
2012-07-29 13:36
537 查看
先啥都不说,看一下MUWork的使用例子,让我们通过代码来感性地认识一下这是个什么东西。
首先,你的程序里必须要有这些文件:
![](http://my.csdn.net/uploads/201207/29/1343532061_3289.jpg)
然后我们声明一个类:
实现它:
再声明一个TestInteceptor类:
实现它
OK,我们来下一步。
在主程序里,我们可以这样写:
我们运行一下程序,会输出什么呢?
改一下这句:
再运行一下,输出下面的结果:
看完上面的例子,相信有不少人已经很清楚MUWork是干什么的了。那么,下面开始正式介绍MUWork。
XWork是一个标准的Command模式实现,并且完全从web层脱离出来。Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL – the Object Graph Navigation Language),IoC(Inversion ofControl反转控制)容器等。
那么,不准确地,MUWork可以概述为:
MUWork是受XWork启发而实现的一个基于Objective-c 语言的Command模式实现。MUWork的实现参照了Struts2的架构,省去了容器部分,由MUAction、MUConfig、MUHandler、MUInterceptor、MUInvocation、MUResult、MUValueStack七个组件构成。其目的是:创建一个泛化的、可重用且可扩展的命令模式框架。
大致可以用下图表示:
![](http://my.csdn.net/uploads/201207/29/1343529042_3253.png)
先来看一下Action类的接口:
注意到该接口只声明一个方法Execute,该方法返回一个id类型的变量。这里的返回值就是核心业务操作的返回结果。
可以看到,execute方法并没有参数,那么业务运算时所需要的数据怎么传入呢?事实上,Action类是通过声明属性获得所有相关的值的。要对action进行数据交互,我们要做的唯一一件事就是在Action类中声明与参数同名的属性,在调用Action的execute方法之前,调度器(MUInvocation)就会为相应的Action属性赋值(注入)。这个功能的实现很大程度依赖于MUValueStack,MUValueStack为访问Action属性提供了一个很方便的途径。
Interceptor本身是AOP的概念,表示对程序的某个逻辑执行点进行拦截,从而能够在
4000
这个逻辑执行点之前、之后或者环绕着这个逻辑执行点进行逻辑扩展。在XWork中,Interceptor的拦截对象是核心处理类Action,从而在Action的周围定义了一个环绕的逻辑扩展层次,其主要作用就在于能够在核心处理类Action的执行之前、之后进行自定义的逻辑行为扩展。
我们来看一下MUInterceptor的接口:
可以看到该接口定义了两个可选方法:
从方法名字可以看出,它们分别在action执行前和执行后调用。其中actionBefore:方法的返回结果决定了业务操作是否继续进行。
MUResult实现了返回结果和表现形式的解耦。在整个command流的最后,MUResult中的parseResult:方法会被调用,返回结果在其中进行最后的包装。
MUValueStack和Structs里面的ValueStack类似,是数据访问的工具,其内部维护着一个小型表达式解释器MUSimpleEL,通过表达式语言对action的属性进行访问和设置。
其中only方法是提供一种不触发拦截器直接执行action的调用途径。
MUSimpleEL
MUSimpleEL是一个非常简单的表达式解释器。
MUDefaultResult
MUResultProtocol的默认实现,只是简单地把传入参数返回。
MUNavigator
MUNavigator是一个基于MUWork的ios开发框架,通过AOP实现了业务逻辑流和界面逻辑流的分离,他可以令你的ViewController里面只有跟界面有关的代码,所有业务逻辑交给Handler处理,并且提供一个相对完善的Delegate回调机制。
关于这部分的文档正在整理中,到时另外一文进行介绍。
首先,你的程序里必须要有这些文件:
![](http://my.csdn.net/uploads/201207/29/1343532061_3289.jpg)
然后我们声明一个类:
#import <Foundation/Foundation.h> #import "MUActionProtocol.h" @interface TestAction : NSObject<MUActionProtocol> { } @property(nonatomic, strong) NSString* name; @end
实现它:
#import "TestAction.h" @implementation TestAction @synthesize name = _name; - (id)execute { NSLog(@"name: %@", _name); return [NSString stringWithFormat:@"Action invoked:%@", _name]; } @end
再声明一个TestInteceptor类:
#import <Foundation/Foundation.h> #import "MUInterceptorProtocol.h" @interface TestInterceptor : NSObject<MUInterceptorProtocol> { } @end
实现它
#import "TestInterceptor.h" #import "MUHandler.h" @implementation TestInterceptor - (BOOL) actionBefore:(MUHandler*) handler { NSLog(@"actionBefore was invoked."); return YES; } - (void) actionAfter:(MUHandler*) handler { NSLog(@"actionAfter was invoked."); } @end
OK,我们来下一步。
在主程序里,我们可以这样写:
TestMUInterceptor* interceptor = [[TestMUInterceptor alloc] init]; TestAction* action = [[TestAction alloc] init]; DefaultMUResult* result = [[DefaultMuResult alloc] init]; MUHandler* handler = [[MUHandler alloc] init]; [handler setAction:action]; [handler setResult:result]; [handler addInterceptor:interceptor]; [handler setContextObject:@"abc" forKey:@"name"]; MUInvocation* invocation = [[MUInvocation alloc] init]; NSLog(@"%@", [invocation invoke:handler]);
我们运行一下程序,会输出什么呢?
2012-07-29 11:01:49.740 TestMUWork[537:5d03] actionBefore was invoked. 2012-07-29 11:01:49.741 TestMUWork[537:5d03] name: abc 2012-07-29 11:01:49.742 TestMUWork[537:5d03] actionAfter was invoked. 2012-07-29 11:01:49.744 TestMUWork[537:5d03] Action invoked:abc
改一下这句:
[handler addInterceptor:interceptor]; //改成: [handler addInterceptor:interceptor]; [handler addInterceptor:[interceptor copy]]; [handler addInterceptor:[interceptor copy]];
再运行一下,输出下面的结果:
2012-07-29 11:01:49.740 TestMUWork[537:5d03] actionBefore was invoked. 2012-07-29 11:01:49.780 TestMUWork[537:5d03] actionBefore was invoked. 2012-07-29 11:01:49.860 TestMUWork[537:5d03] actionBefore was invoked. 2012-07-29 11:01:49.920 TestMUWork[537:5d03] name: abc 2012-07-29 11:01:49.980 TestMUWork[537:5d03] actionAfter was invoked. 2012-07-29 11:01:50.005 TestMUWork[537:5d03] actionAfter was invoked. 2012-07-29 11:01:50.015 TestMUWork[537:5d03] actionAfter was invoked. 2012-07-29 11:01:50.035 TestMUWork[537:5d03] Action invoked:abc
看完上面的例子,相信有不少人已经很清楚MUWork是干什么的了。那么,下面开始正式介绍MUWork。
1. MUWork是什么
先来看一下百度百科里面关于XWork的简介:XWork是一个标准的Command模式实现,并且完全从web层脱离出来。Xwork提供了很多核心功能:前端拦截机(interceptor),运行时表单属性验证,类型转换,强大的表达式语言(OGNL – the Object Graph Navigation Language),IoC(Inversion ofControl反转控制)容器等。
那么,不准确地,MUWork可以概述为:
MUWork是受XWork启发而实现的一个基于Objective-c 语言的Command模式实现。MUWork的实现参照了Struts2的架构,省去了容器部分,由MUAction、MUConfig、MUHandler、MUInterceptor、MUInvocation、MUResult、MUValueStack七个组件构成。其目的是:创建一个泛化的、可重用且可扩展的命令模式框架。
大致可以用下图表示:
![](http://my.csdn.net/uploads/201207/29/1343529042_3253.png)
2. MUWork的结构
MUWork由七个组件构成,大致可以用下图表示:1. MUAction:
据我自己的不完全理解,action类代表了业务的核心操作,是处理“你要完成的事情”的地方。先来看一下Action类的接口:
#import <Foundation/Foundation.h> @protocol MUActionProtocol <NSObject> - (id)execute; @end
注意到该接口只声明一个方法Execute,该方法返回一个id类型的变量。这里的返回值就是核心业务操作的返回结果。
可以看到,execute方法并没有参数,那么业务运算时所需要的数据怎么传入呢?事实上,Action类是通过声明属性获得所有相关的值的。要对action进行数据交互,我们要做的唯一一件事就是在Action类中声明与参数同名的属性,在调用Action的execute方法之前,调度器(MUInvocation)就会为相应的Action属性赋值(注入)。这个功能的实现很大程度依赖于MUValueStack,MUValueStack为访问Action属性提供了一个很方便的途径。
2. MUInterceptor:
顾名思义,MUInterceptor为拦截器,是实现AOP的核心元素。借用一下downpour在《拦截器详解》里面对interceptor的定义:Interceptor本身是AOP的概念,表示对程序的某个逻辑执行点进行拦截,从而能够在
4000
这个逻辑执行点之前、之后或者环绕着这个逻辑执行点进行逻辑扩展。在XWork中,Interceptor的拦截对象是核心处理类Action,从而在Action的周围定义了一个环绕的逻辑扩展层次,其主要作用就在于能够在核心处理类Action的执行之前、之后进行自定义的逻辑行为扩展。
我们来看一下MUInterceptor的接口:
#import <Foundation/Foundation.h> @class MUHandler; @protocol MUInterceptorProtocol <NSObject> @optional - (BOOL) actionBefore:(MUHandler*) handler; - (void) actionAfter:(MUHandler*) handler; @end
可以看到该接口定义了两个可选方法:
- (BOOL) actionBefore:(MUHandler*) handler; - (void) actionAfter:(MUHandler*) handler;
从方法名字可以看出,它们分别在action执行前和执行后调用。其中actionBefore:方法的返回结果决定了业务操作是否继续进行。
3. MUResult:
#import <Foundation/Foundation.h> @protocol MUResultProtocol <NSObject> - (id)parseResult:(id) result @end
MUResult实现了返回结果和表现形式的解耦。在整个command流的最后,MUResult中的parseResult:方法会被调用,返回结果在其中进行最后的包装。
4. MUHandler:
#import <Foundation/Foundation.h> #import "MUInterceptorProtocol.h" #import "MUActionProtocol.h" #import "MUResultProtocol.h" #import "MUValueStack.h" @interface MUHandler : NSObject { NSMutableDictionary* _contextDictionary; NSMutableArray* _interceptorArray; id<MUActionProtocol> _action; id<MUResultProtocol> _result; MUValueStack* _valueStack; } @property(nonatomic, strong) id<MUActionProtocol> action; @property(nonatomic, strong) id<MUResultProtocol> result; @property(nonatomic, readonly) MUValueStack* valueStack; @property(nonatomic, strong) NSMutableArray* interceptorArray; @property(nonatomic, copy) NSString* name; //interceptor - (void) addInterceptor:(id<MUInterceptorProtocol>) interceptor; - (void) removeInterceptorAtIndex:(NSInteger) index; - (void) removeInterceptor:(id<MUInterceptorProtocol>) interceptor; //context - (void) setContextObject:(id) object forKey:(id) key; - (id) contextObjectForkey:(id) key; - (void) removeContextObject:(id) key; - (NSDictionary*) contextDictionary; @endMUHandler是Action、interceptor、result、ValueStack实例的载体,同时其内部维护着一个contextDictionary,是整个业务过程中的数据载体。从其中的方法可以看出,通过handler可以添加或者删除interceptor,或者增删contextDictionary里面的数据。可以总结为:MUHandler既是控制流的访问接口,同时也是数据流的访问接口,可以利用interceptor通过handler对控制流和数据流进行操作,以实现command模式。
5. MUValueStack:
#import <Foundation/Foundation.h> #import "MUSimpleEL.h" @interface MUValueStack : NSObject { NSMutableArray* _objectArray; MUSimpleEL* _simpleEL; } - (void)pushObject:(id) object; - (id)popObject; - (id)peek; - (id)getValue:(NSString*) expression; - (void)setValue:(NSString*) expression value:(id) value; @end
MUValueStack和Structs里面的ValueStack类似,是数据访问的工具,其内部维护着一个小型表达式解释器MUSimpleEL,通过表达式语言对action的属性进行访问和设置。
6. MUInvocation:
#import <Foundation/Foundation.h> #import "MUHandler.h" @interface MUInvocation : NSObject { } - (id)invoke:(MUHandler*) handler; - (id)onlyInvokeAction:(MUHandler*) handler; @endMUInvocation是整个command流的总调度器,负责interceptor和action调用的次序。当Handler初始化完毕后,传入invocation的invoke方法,整个command模式即可启动。
其中only方法是提供一种不触发拦截器直接执行action的调用途径。
7. MUConfig:
#import <Foundation/Foundation.h> #import "MUHandler.h" @protocol MUConfigProtocol <NSObject> + (MUHandler*) getHandler:(NSInteger) type; @endMUConfigProcotol是一个辅助MUHandler进行初始化的简单工厂接口。
8. 其他:
MUActionInjector#import <Foundation/Foundation.h> #import "MUActionProtocol.h" #import "MUHandler.h" @interface MUActionInjector : NSObject + (void) injectHandler:(MUHandler*) handler intoAction:(id<MUActionProtocol>) action; @end
#import "DefaultMUResult.h" @implementation DefaultMUResult - (id)parseResult:(id) result { return result; } @end此类主要是负责自动地对action进行属性注入。虽然可以通过设置Interceptor和valuestack完成这样的工作,但是这里为了不在业务流里掺杂与框架相关的操作流,所以交给了一个特定的类来进行。
MUSimpleEL
#import <Foundation/Foundation.h> @interface MUSimpleEL : NSObject - (id)executeExpression:(NSString*) expression context:(NSDictionary*) context root:(id) root; @end
MUSimpleEL是一个非常简单的表达式解释器。
MUDefaultResult
#import "DefaultMUResult.h" @implementation DefaultMUResult - (id)parseResult:(id) result { return result; } @end
MUResultProtocol的默认实现,只是简单地把传入参数返回。
3. 源码下载
源码已上传到GitHub,点击下载源代码4.基于MUWork的一些东西
写完这个框架以后,我决定要用它来做点什么。由于我是一个ios开发者,所以打算把MUWork用在这一方面。经过几天的努力和几十天的修改,有了下面的东西:MUNavigator
MUNavigator是一个基于MUWork的ios开发框架,通过AOP实现了业务逻辑流和界面逻辑流的分离,他可以令你的ViewController里面只有跟界面有关的代码,所有业务逻辑交给Handler处理,并且提供一个相对完善的Delegate回调机制。
关于这部分的文档正在整理中,到时另外一文进行介绍。
相关文章推荐
- Spring AOP编程(两种:1,传统的AOP切面编程 2,基于aspectj框架切点传统开发)
- JointCode.Aspects,一个基于装饰模式的 Aop 框架
- Tangram:一个基于MFC框架的柔性软件开发系统
- Jersey—— 一个基于Rest风格的Web Service开发框架
- 分享一个基于 Node.js 的 Web 开发框架 - Nokitjs
- 基于ACE Proactor框架下高并发、大容量吞吐程序设计既最近的一个产品开发总结
- 基于ACE Proactor框架下高并发、大容量吞吐程序设计既最近的一个产品开发总结
- Tangram:一个基于MFC框架的柔性软件开发系统
- 一个专为移动端开发的原创即时通讯框架,超轻量级、高度提炼,完全基于UDP协议,支持iOS、Android、标准Java平台。
- 基于ACE Proactor框架下高并发、大容量吞吐程序设计既最近的一个产品开发总结
- Wizard Framework:一个自己开发的基于Windows Forms的向导开发框架
- 汇总:基于SSM封装的一个迅速开发项目的底层框架集成项目
- 基于ACE Proactor框架下高并发、大容量吞吐程序设计既最近的一个产品开发总结
- 分享一个简易的ORM框架源代码以及基于该框架开发的一个简易论坛源代码
- 【原创】基于ACE Proactor框架下高并发、大容量吞吐程序设计既最近的一个产品开发总结
- Wizard Framework:一个自己开发的基于Windows Forms的向导开发框架
- 基于Spring开发的一个BIO-RPC框架(对小白很友好)
- 分享一个基于 Node.js 的 Web 开发框架 - Nokitjs
- Tangram:一个基于MFC框架的柔性软件开发系统
- 【原创】基于ACE Proactor框架下高并发、大容量吞吐程序设计既最近的一个产品开发总结