js实现的AOP雏形

  老早以前的东西了,发出来分享下。目前支持aop的框架实在很少,功能也挺残废的~ 运行还算稳定,不会对this指针造成干扰,经测试可对对象的方法、独立函数、构造函数等各种添加AOP支持,也可以解除AOP支持。使用advice链式结构实现,最大的特点应该是支持参数/返回值控制(即每个advice均有一个入口/出口,可以自由定制输入/输出策略)。不多说了,上代码,直接拿来用应该是木有问题的但是目前还只实现了before和after两个joinpoint,后续可能扩展一些,参数/返回值策略也有些小单调虽然扩展性不咋地但是基本需求应该能满足。后续如果有时间的话可能从这两点完善一下。

//外部接口

var AopUtil = {};

(function() {

AopUtil.ALLOW_IN = 1;

AopUtil.ALLOW_OUT = 2;

var original = {};

//缓存数据,新增before advice的时候会用到

var beforeAdviceCounter = 0;

//将原始方法变成代理方法的方法

var createProxyMethod = function(originalItem) {

return function() {

var currentArg = arguments;

var currentReturn = arguments;

var lastReturn = arguments;

//计算组合策略(参数+返回值策略)中的参数策略

//isInAllowed为策略值二进制表示中的最低位值,isOutAllowed为次低位

var isInAllowed, isOutAllowed;

//当前函数的返回值

var result;

for (var i in originalItem.adviceChain) {

//读取策略组

isInAllowed = originalItem.adviceChain[i].strategy;

isOutAllowed = isInAllowed >> 1;

isInAllowed = isInAllowed - (isInAllowed >> 1 << 1);

isOutAllowed = isOutAllowed - (isOutAllowed >> 1 << 1);

if (isInAllowed) currentArg = lastReturn;

else currentArg = arguments;

currentReturn = [originalItem.adviceChain[i].method.apply(this, currentArg)];

if (isOutAllowed) lastReturn = currentReturn;

}

return lastReturn[0];

}

}

//对原始方法添加AOP支持

var attachToAop = function(methodName, strategy) {

if (original[methodName]) return null;

var sourceMethod = eval(methodName);

if (!sourceMethod) return null;

//初始化adviceChain

original[methodName] = {};

original[methodName].backup = sourceMethod;

original[methodName].adviceChain = [{method : sourceMethod, strategy : strategy}];

eval(methodName + " = createProxyMethod(original[methodName])");

}

//外部接口之添加before joinpoint

AopUtil.before = function(methodName, command, strategy) {

if (!original[methodName]) attachToAop(methodName, 3);

original[methodName].adviceChain.splice(

beforeAdviceCounter, 0, {

method : command,

strategy : (strategy ? strategy : AopUtil.SKIP_ARG)

}

);

++beforeAdviceCounter;

}

//外部接口之添加after joinpoint

AopUtil.after = function(methodName, command, strategy) {

//原始函数两端全开

if (!original[methodName]) attachToAop(methodName, 3);

original[methodName].adviceChain.push({

method : command,

strategy : (strategy ? strategy : AopUtil.SKIP_ARG)

});

}

//清空目标方法上的所有advice

AopUtil.clearAdvice = function(methodName) {

if (original[methodName]) {

eval(methodName + "= original[methodName].backup");

original[methodName] = null;

}

}
})();



靠,在这个编辑器里头调格式真够累的...下面是使用实例



//先定义一个类

var Class = function() {

//私有成员变量

var value = "value";

this.alert = function() {

alert(value);

}

this.setValue = function(newValue) {

value = newValue;

}

}

AopUtil.before("Class", function() {

alert("你正在初始化一个实例!");

});

//初始化一个实例,这个时候会输出"你正在初始化一个实例!"这句话;

//实际上,当直接执行"Class()"的时候也会输出这句话。如果仅希望在Class被当做构造函数使用时输出,

//可以通过this指针来判断,就像这样:

//AopUtil.before("Class", function() {

// if (!typeof(this).toLowerCase() == "object") alert("你没有把Class当做构造函数!");

// else alert("你正在初始化一个实例!");

//});

var a = new Class();

//比较高级的应用:

AopUtil.before("a.alert", function() {

alert(0);

}, AopUtil.ALLOW_IN + AopUtil.ALLOW_OUT);

AopUtil.before("a.alert", function() {

alert(1);

}, AopUtil.ALLOW_IN + AopUtil.ALLOW_OUT);

AopUtil.before("a.alert", function() {

alert(2);

}, AopUtil.ALLOW_IN + AopUtil.ALLOW_OUT);

AopUtil.after("a.alert", function() {

alert(3);

}, AopUtil.ALLOW_IN + AopUtil.ALLOW_OUT);

AopUtil.after("a.alert", function() {

alert(4);

}, AopUtil.ALLOW_IN + AopUtil.ALLOW_OUT);

AopUtil.after("a.alert", function() {

alert(5);

}, AopUtil.ALLOW_IN + AopUtil.ALLOW_OUT);

//有兴趣的同僚们觉得执行"a.alert()"的时候应该输出啥?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值