|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
还是要自己一点一点写代码,然后编译,改错再编译好那。还有最重要的是.net网页编程的编译环境非常好,你甚是不需要了解太多工具,对于简单的系统,你可以之了解一些语法就哦了。日前公布的dojo1.7版本对其源码举行了很年夜的变动。在迈向2.0版本之际,dojo供应了很多新的功效,也对很多已有的功效举行了修正,详细来讲新版本更好地撑持AMD标准、供应了新的事务处置体系(企图在2.0版本中交换dojo.connectAPI)和DOM查询模块、更新对象存储相干接口(ObjectStore)等。在本文中我们将会先容在dojo1.7版本中新增的面向方面编程(AOP)功效和实在现道理。
1.简介
AOP即面向方面编程,是面向对象编程头脑的持续。使用该头脑剥离一些通用的营业,能够无效下降营业逻辑间的耦合度,进步程序的可重用性。跟着Java范畴中Spring框架的盛行,其倡议的AOP理念被更多的人所熟悉(要注重的是Spring并非该头脑的创始者,但说Spring框架的盛行让更多人懂得和进修了AOP头脑其实不为过)。由于Java为静态言语,以是在完成AOP功效时较为庞大,一样平常接纳两种体例即静态代办署理和字节码天生手艺(如CGLib)来完成该功效。在JavaScript范畴,由于之前模块化需求并非很激烈,以是AOP的理念并没有被普遍引进出去。可是跟着RIA手艺的开展,愈来愈多的营业逻辑在前台完成,JavaScript代码的构造和可保护性更加主要,恰是在如许的背景下,呈现了良多JavaScript模块化办理的类库,而dojo也在这方面主动探究,新版本的dojo已更好地撑持AMD标准,并供应了面向方面编程的撑持。
在面向方面编程功效推出之前,dojo能够经由过程利用connect办法来完成相似的功效。connect办法次要能够完成两类功效即为dom对象绑定事务和为已有的办法增加后置办法。已有很多文章剖析dojo的connect办法的利用和道理,再加上dojo企图在未来版本中移除该API,以是在此不合错误这个办法举行更仔细的剖析了。
2.dojo的aspect模块利用简介
在dojo1.7的版本中新增了aspect模块,该模块次要用来完成AOP的功效。借助于此项功效能够为某个对象的办法在运转时增加before、after或around范例的加强(advice,即要实行的切面办法)。为了先容此功效,我们先用dojo的类机制声明一个复杂的类:- 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(){returnthis.name;},getAge:function(){returnthis.age;},sayMyself:function(){alert("Personsnameis"+this.getName()+"!");}});})
复制代码 这里声明类的办法,与我们在先容类机制时略有分歧,由于dojo从1.6版本入手下手撑持AMD标准,经由过程define办法来声明模块及其依附干系。有了类今后,我们必要创立一个实例,以下:- dojo.require("com.levinzhang.Person");varperson=newcom.levinzhang.Person("levin",30);
复制代码 如今我们要借助dojo的aspect模块为这个类的实例增加AOP功效。假定我们必要在sayMyself办法的挪用前后分离增加对另外一个办法的挪用(即所谓的加强advice),示例代码以下:- varaspect=dojo.require("dojo.aspect");//引进aspect模块//声明在person的sayMyself办法挪用前要挪用的办法varsignal=aspect.before(person,"sayMyself",function(){alert("挪用了before");});//声明在person的sayMyself办法挪用后要挪用的办法aspect.after(person,"sayMyself",function(){alert("挪用了after");});//此时挪用sayMyself办法将会前后打印出://“挪用了before”、“Personsnameislevin!”、“挪用了after”//即依照before、方针办法、after的按次实行person.sayMyself();
复制代码 在以上的代码片断中,我们利用了aspect的before和after办法完成了在方针办法前后增加advice。在挪用before和after办法后将会前往一个signal对象,这个对象纪录了方针advice并供应了移除办法,如要移除上文增加的beforeadvice,只需实行以下代码:- signal.remove();//移除后面增加的beforeadvice//此时挪用sayMyself办法将会前后打印出://“Personsnameislevin!”、“挪用了after”//即经由过程aspect.before增加的办法已被移除person.sayMyself();
复制代码 除before和after范例的advice,dojo还撑持around范例的advice,在这类情形下,必要前往一个function,在这个function中能够增加恣意的营业逻辑代码并挪用方针办法,示例代码以下:- varsignal=aspect.around(person,"sayMyself",function(original){returnfunction(){alert("beforetheoriginalmethod");original.apply(person,arguments);//挪用方针办法,即原始的sayMyself办法alert("aftertheoriginalmethod");}});//此时挪用sayMyself办法将会前后打印出://“beforetheoriginalmethod”、“Personsnameislevin!”、“aftertheoriginalmethod”person.sayMyself();
复制代码 从下面的示例代码我们能够看到,around范例的advice会有更多对营业逻辑的把持权,原始的方针办法会以参数的情势传送出去,以便在advice中举行挪用。
经由过程对以上几品种型advice利用体例的先容,我们能够看到dojo的AOP功效在JavaScript中完成了AOPAlliance所倡议的advice范例。必要指出的是,每品种型的advice都可增加多个,dojo会依照增加的按次顺次实行。
3.完成道理
懂得了dojoAOP功效的基础语法后,让我们剖析一下实在现道理。dojoaspect模块的完成在dojo/aspect.js文件中,全部文件的代码数在100行摆布,因而实在现是相称简便高效的。
经由过程varaspect=dojo.require("dojo.aspect");办法引进该模块时,会失掉一个复杂的JavaScript对象,我们挪用aspect.before、aspect.around、aspect.after时,均会挪用该文件中界说的aspect办法所前往的function。- define([],function(){……return{before:aspect("before"),around:aspect("around"),after:aspect("after")};});
复制代码 如今我们看一下aspect办法的完成:- functionaspect(type){//关于分歧范例的advice均前往此办法,只不外type参数会有所分歧returnfunction(target,methodName,advice,receiveArguments){varexisting=target[methodName],dispatcher;if(!existing||existing.target!=target){//经由AOP处置的办法均会被一个新的办法所交换,也就是这里的dispatcherdispatcher=target[methodName]=function(){//beforeadvicevarargs=arguments;//失掉第一个before范例的advicevarbefore=dispatcher.before;while(before){//挪用before范例的adviceargs=before.advice.apply(this,args)||args;//找到下一个before范例的advicebefore=before.next;}//挪用around范例的adviceif(dispatcher.around){挪用dispatcher.around的advice办法varresults=dispatcher.around.advice(this,args);}//失掉第一个after范例的advicevarafter=dispatcher.after;while(after){//挪用after范例的adviceresults=after.receiveArguments?after.advice.apply(this,args)||results:after.advice.call(this,results);//找到下一个after范例的adviceafter=after.next;}returnresults;};if(existing){//设置最后的around范例的advice,即挪用方针办法dispatcher.around={advice:function(target,args){returnexisting.apply(target,args);}};}dispatcher.target=target;}//关于分歧范例的advice,通用advise办法来修正dispatcher,即对象的同名办法varresults=advise((dispatcher||existing),type,advice,receiveArguments);advice=null;returnresults;};}
复制代码 我们能够看到,在第一次挪用aspect办法时,原本的方针办法会被交换成dispatcher办法,而在这个办法中会依照外部的数据布局,顺次挪用各类范例的advice和最后的方针办法。而构建和调剂这个外部数据布局是经由过程advise办法来完成的:- functionadvise(dispatcher,type,advice,receiveArguments){varprevious=dispatcher[type];//失掉指定范例的前一个advicevararound=type=="around";varsignal;if(around){//对around范例的advice,只需挪用advice办法,并将上一个advice(有大概即为//方针办法)作为参数传进便可varadvised=advice(function(){returnprevious.advice(this,arguments);});//构建前往的对象,即aspect.around办法的前往值signal={//移除办法remove:function(){signal.cancelled=true;},advice:function(target,args){//即为真正实行的around办法returnsignal.cancelled?previous.advice(target,args)://作废,跳至下一个advised.apply(target,args);//挪用后面的advised办法}};}else{//关于after或before范例的advice,构建移除办法signal={remove:function(){varprevious=signal.previous;varnext=signal.next;if(!next&&!previous){deletedispatcher[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加到列表的尾部varnext=previous;while(next){//移到链表尾部previous=next;next=next.next;}previous.next=signal;signal.previous=previous;}elseif(type=="before"){//将新增的advice增加到肇端地位dispatcher[type]=signal;signal.next=previous;previous.previous=signal;}}else{//around范例的advice或第一个advicedispatcher[type]=signal;}returnsignal;}
复制代码 以上,我们剖析了dojo的aspect模块的利用和完成道理,只管这类将静态言语编程作风移植到剧本言语中的做法可否被人人承受并普遍利用另有待工夫的查验,但这类实验和完成体例仍是很值得自创的。
参考材料
- http://livedocs.dojotoolkit.org/
- http://dojotoolkit.org/
关于作者
张卫滨,存眷企业级Java开辟和RIA手艺,团体博客:http://lengyun3566.iteye.com,微博:http://weibo.com/zhangweibin1981
Java编译的是字节码,跟C++相反,启动不够快,效率不够高,难以精确控制内存,但是优点是编程比C++容易,代码比较安全但是容易留下性能隐患,跨平台靠字节码在各个平台复制(一处编译到处调试) |
|