读书人

dojo1.7效能介绍:面向方面编程(AOP)

发布时间: 2012-07-24 17:47:58 作者: rapoo

dojo1.7功能介绍:面向方面编程(AOP)功能与原理

声明:本文为笔者原创,但首发于InfoQ中文站,详见文末声明

?

?

define("com.levinzhang.Person",["dojo/_base/declare"],function(declare){declare("com.levinzhang.Person", null,{name:null,age:null,constructor: function(name,age){this.name = name;this.age = age;},getName:function(){return this.name;},getAge:function(){return this.age;},sayMyself:function(){alert("Person's name is "+this.getName()+"!");}});})?

?

dojo.require("com.levinzhang.Person");var person = new com.levinzhang.Person("levin",30);?

var aspect = dojo.require("dojo.aspect");//引入aspect模块//声明在person 的sayMyself方法调用前要调用的方法var signal = aspect.before(person,"sayMyself",function(){alert("调用了before");});//声明在person 的sayMyself方法调用后要调用的方法aspect.after(person,"sayMyself",function(){alert("调用了after");});//此时调用sayMyself方法将会先后打印出://“调用了before”、“Person's name is levin!”、“调用了after”//即按照before、目标方法、after的顺序执行person.sayMyself();?

signal.remove();//移除前面添加的beforeadvice//此时调用sayMyself方法将会先后打印出:// “Person's name is levin!”、“调用了after”//即通过aspect.before添加的方法已经被移除person.sayMyself();?

var signal = aspect.around(person, "sayMyself", function(original){return function(){alert("before the original method");original.apply(person,arguments);//调用目标方法,即原始的sayMyself方法alert("after the original method");}}); //此时调用sayMyself方法将会先后打印出://“before the original method”、“Person's name is levin!”、“after the original method”person.sayMyself();?

define([], function(){……return {before: aspect("before"),around: aspect("around"),after: aspect("after")};});?

?

function aspect(type){ //对于不同类型的advice均返回此方法,只不过type参数会有所不同return function(target, methodName, advice, receiveArguments){var existing = target[methodName], dispatcher;if(!existing || existing.target != target){//经过AOP处理的方法均会被一个新的方法所替换,也就是这里的dispatcherdispatcher = target[methodName] = function(){// before advicevar args = arguments; //得到第一个before类型的advicevar before = dispatcher.before; while(before){ //调用before类型的adviceargs = before.advice.apply(this, args) || args; //找到下一个before类型的advicebefore = before.next;}//调用around类型的adviceif(dispatcher.around){ 调用dispatcher.around的advice方法var results = dispatcher.around.advice(this, args);}//得到第一个after类型的advicevar after = dispatcher.after;while(after){ //调用after类型的adviceresults = after.receiveArguments ? after.advice.apply(this, args) || results : after.advice.call(this, results); //找到下一个after类型的adviceafter = after.next;}return results;};if(existing){ //设置最初的around类型的advice,即调用目标方法dispatcher.around = {advice: function(target, args){return existing.apply(target, args);}};}dispatcher.target = target;} //对于不同类型的advice,通用advise方法来修改dispatcher,即对象的同名方法var results = advise((dispatcher || existing), type, advice, receiveArguments);advice = null;return results;};}?

function advise(dispatcher, type, advice, receiveArguments){var previous = dispatcher[type];//得到指定类型的前一个advicevar around = type == "around";var signal;if(around){ //对around类型的advice,只需调用advice方法,并将上一个advice(有可能即为//目标方法)作为参数传入即可var advised = advice(function(){return previous.advice(this, arguments);}); //构建返回的对象,即aspect.around方法的返回值signal = { //移除方法remove: function(){signal.cancelled = true;},advice: function(target, args){ //即为真正执行的around方法return signal.cancelled ?previous.advice(target, args) : //取消,跳至下一个advised.apply(target, args);// 调用前面的advised方法}};}else{// 对于after或before类型的advice,构建移除方法signal = {remove: function(){var previous = signal.previous;var next = signal.next;if(!next && !previous){delete dispatcher[type];}else{if(previous){previous.next = next;}else{dispatcher[type] = next;}if(next){next.previous = previous;}}},advice: advice,receiveArguments: receiveArguments};}if(previous && !around){if(type == "after"){//将新增的advice加到列表的尾部var next = previous;while(next){ //移到链表尾部previous = next;next = next.next;}previous.next = signal;signal.previous = previous;}else if(type == "before"){//将新增的advice添加到起始位置dispatcher[type] = signal;signal.next = previous;previous.previous = signal;}}else{// around类型的advice或第一个advicedispatcher[type] = signal;}return signal;}?

?

?

读书人网 >编程

热点推荐