基于js的简易aop框架

AOP参考资料:

来自百度   来自IBM

 

aop在spring中大量被使用到,说白了就是往目标代码中织入关注的切面代码,在spring中需要使用proxy或cglib中实现。

鉴于JavaScript的灵活性,在js中实现aop比想象中灵活得多。

 

下面写了个简单的实现,需要比较粗糙,pointcut什么的没有体验,但总体思想和aop一致。

 

 

1、

 

/*
			绑定的AOP
			*/
			bind:function(obj,advice){
				//如果已经绑定过了,就不再重复绑定了
				if(oldObjectFn[obj]!=null){
					return;
				}
				//生成织入器
				var inject=injectCreator(advice);
				dealObjectFunction(obj,inject);
			}

 aop绑定的入口在这里,这里根据传入的advice生成一个织入器。

 

 

2、

 

function dealObjectFunction(obj,inject){
			oldObjectFn[obj]={};
			
			for(var name in obj){
				
				if(obj.hasOwnProperty(name)){//原型链下的属性不操作
					var val=obj[name];
					if(isFunction(val)){//只操作function
						var oldfn=val;
						var newfn=inject(name,val,obj);//把切面代码织入到旧代码中
						obj[name]=newfn;
						oldObjectFn[obj][name]=oldfn;//旧方法保存起来
					}
				}
			}
		}

 筛选出目标函数,当然这里写的比较粗糙,只是简单把所有的方法的取出来(没得选)

 

 

var newfn=inject(name,val,obj)

 通过这个方法,编织出一个新的函数,保存旧函数,并替换目标函数。

 

 

3、 织入代码的具体实现

var injectCreator=function(advice){
			return function(name,oldfn,obj){	
					
				var before=advice.before||function(){},
				after=advice.after||function(){},
				afterReturn=advice.afterReturn||function(){},
				afterThrowing=advice.afterThrowing||function(){},
				around=advice.around||function(fn){
					var ret=fn();
					return ret;
				},
				
				fn=function(){

					var args=Array.prototype.slice.call(arguments);
					
					before.apply(obj,[name].concat(args)); //前置通知带上方法明
					
					var ret=around.call(obj,function(){
						try{
							return oldfn.apply(obj,args); //执行原有方法,并返回原方法的执行结果
						}catch(e){
							afterThrowing.call(obj,e);
							throw e;
						}
					});
					afterReturn.call(obj,ret);  
					after.call(obj);
					
					return ret;
				};
				
				return fn;
			}
		}

 

对advice进行简单修饰后,按先后顺序用before、around、afterReturn、after对旧方法进行装饰,放回新方法。

 

var args=Array.prototype.slice.call(arguments);

 因为arguments不是数组,为了让他居然数组的特性,进行上面的处理。

 

4、解绑

unbind:function(obj){
				var map=oldObjectFn[obj];
				if(map!=null){
					//把旧的方法放回去
					for(var key in map){
						var fn=map[key];
						obj[key]=fn;
					}
					oldObjectFn[obj]=null;
				}
				
			}

 

你可能感兴趣的:(JavaScript,AOP)