??xml version="1.0" encoding="utf-8" standalone="yes"?>
1. AJAX: 状态驻留,异步更新
首先来看一点历双Ӏ?br />A. 1995qNetscape公司的Brendan Eich开发了javacript语言Q这是一U动?dynamic)、弱cd(weakly typed)、基于原?prototype-based)的脚本语a?br />B. 1999q微软IE5发布Q其中包含了XMLHTTP ActiveX控g?br />C. 2001q微软IE6发布Q部分支持DOM level 1和CSS 2标准?br />D. 2002qDouglas Crockford发明JSON格式?br />xQ可以说Web2.0所依赖的技术元素已l基本成形,但是q没有立d整个业界产生重大的媄响。尽一?#8220;面异步局部刷?#8221;的技巧在E序员中间秘密的传Q甚臛_生了bindowsq样庞大臃肿的类库,但ȝ来说Q前端被看作是瘠而又肮脏的沼泽地Q只有后台技术才是王道。到底还~少些什么呢Q?br /> 当我们站在今天的角度d?005q之前的js代码Q包括那些当时的牛h所写的代码Q可以明昄感受到它们在E序控制力上的孱弱。ƈ不是?005q之前的js技术本w存在问题,只是它们在概念层面上是一盘散沙,~Zl一的观念,或者说~少自己独特的风? 自己的灵。当时大多数的hQ大多数的技术都试图在模拟传l的面向对象语言Q利用传l的面向对象技术,dCl的GUI模型的仿制品?br /> 2005q是变革的一q_也是创造概늚一q。伴随着Google一pd让h耳目一新的交互式应用的发布,Jesse James Garrett的一文章《Ajax: A New Approach to Web Applications》被qؓ传播。Ajaxq一前端Ҏ的概念迅速将众多分散的实늻一在同一口号之下Q引发了Web~程范式的{换。所谓名不正则言不顺Q这下无名群众可扑ֈl织了。在未有Ajax之前Qh们早已认识到了B/S架构的本质特征在于浏览器和服务器的状态空间是分离的,但是一般的解决Ҏ都是隐藏q一区分Q将前台状态同步到后台Q由后台l一q行逻辑处理Q例如ASP.NET。因为缺乏成熟的设计模式支持前台状态驻留,在换늚时候,已经装蝲的js对象被q被丢弃Q这栯q能指望它去完成什么复杂的工作吗?
Ajax明确提出界面是局部刷新的Q前台驻留了状态,q就促成了一U需要:需要js对象在前台存在更长的旉。这也就意味着需要将q些对象和功能有效的理hQ意味着更复杂的代码l织技术,意味着Ҏ块化Q对公共代码基的渴求?br /> jQuery现有的代码中真正与Ajax相关Q用XMLHTTP控g异步讉K后台q回数据Q的部分其实很少Q但是如果没有Ajax, jQuery作ؓ公共代码Zq乏存在的理由?br />
2. 模块化:理名字I间
当大量的代码产生出来以后Q我们所需要的最基础的概念就是模块化Q也是对工作进行分解和复用。工作得以分解的关键在于各h独立工作的成果可以集成在一赗这意味着各个模块必须Z一致的底层概念Q可以实C互,也就是说应该Z一套公׃码基Q屏蔽底层浏览器的不一致性,q实现统一的抽象层Q例如统一的事件管理机制等。比l一代码基更重要的是Q各个模块之间必L有名字冲H。否则,即两个模块之间没有M交互Q也无法共同工作?br /> jQuery目前鼓吹的主要卖点之一是对名字空间的良好控制。这甚至比提供更多更完善的功能点都重要的多。良好的模块化允许我们复用Q何来源的代码Q所有h的工作得以积累叠加。而功能实C仅是一时的工作量的问题。jQuery使用module pattern的一个变U来减少对全局名字I间的媄?仅仅在window对象上增加了一个jQuery对象(也就?函数)?br /> 所谓的module pattern代码如下Q它的关键是利用匿名函数限制临时变量的作用域?br /> var feature =(function() {
// U有变量和函?br />var privateThing = 'secret',
publicThing = 'not secret',
changePrivateThing = function() {
privateThing = 'super secret';
},
sayPrivateThing = function() {
console.log(privateThing);
changePrivateThing();
};
// q回对外公开的API
return {
publicThing : publicThing,
sayPrivateThing : sayPrivateThing
}
})();
js本n~Z包结构,不过l过多年的尝试之后业内已l逐渐l一了对包加载的认识QŞ成了RequireJs库这样得C定共识的解决Ҏ。jQuery可以与RequireJS库良好的集成在一? 实现更完善的模块依赖理。http://requirejs.org/docs/jquery.html
require(["jquery", "jquery.my"], function() {
//当jquery.js和jquery.my.js都成功装载之后执?br /> $(function(){
$('#my').myFunc();
});
});
通过以下函数调用来定义模块my/shirt, 它依赖于my/cart和my/inventory模块Q?br /> require.def("my/shirt",
["my/cart", "my/inventory"],
function(cart, inventory) {
// q里使用module pattern来返回my/shirt模块对外暴露的API
return {
color: "blue",
size: "large"
addToCart: function() {
// decrement是my/inventory对外暴露的API
inventory.decrement(this);
cart.add(this);
}
}
}
);
3. 奇?Q对象提?br /> 当你W一眼看?函数的时候,你想C什么?传统的编E理论L告诉我们函数命名应该准确Q应该清晰无误的表达作者的意图Q甚臛_U长名字要优于短名字Q因为减了出现歧义的可能性。但是,$是什么?qQ它所传递的信息实在是太隐晦Q太暧昧了?是由prototype.js库发明的Q它真的是一个神奇的函数Q因为它可以一个原始的DOM节点提升(enhance)Z个具有复杂行为的对象。在prototype.js最初的实现中,$函数的定义ؓ
var $ = function (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};
q基本对应于如下公式
e = $(id)
q绝不仅仅是提供了一个聪明的函数名称~写Q更重要的是在概念层面上建立了文本id与DOM element之间的一一对应。在未有$之前Qid与对应的element之间的距d分遥q,一般要element~存到变量中Q例?br /> var ea = docuement.getElementById('a');
var eb = docuement.getElementById('b');
ea.style....
但是使用$之后Q却随处可见如下的写?br /> $('header_'+id).style...
$('body_'+id)....
id与element之间的距M乎被消除了,可以非常紧密的交l在一赗?br /> prototype.js后来扩展?的含义,
function $() {
var elements = new Array();
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string')
element = document.getElementById(element);
if (arguments.length == 1)
return element;
elements.push(element);
}
return elements;
}
q对应于公式
[e,e] = $(id,id)
很遗憾,q一步prototype.js走偏了,q一做法很少有实用的价倹{?br /> 真正?发扬光大的是jQuery, 它的$对应于公?br /> [o] = $(selector)
q里有三个增?br /> A. selector不再是单一的节点定位符Q而是复杂的集合选择W?br /> B. q回的元素不是原始的DOM节点Q而是l过jQueryq一步增强的h丰富行ؓ的对象,可以启动复杂的函数调用链?br /> C. $q回的包装对象被造型为数lŞ式,集合操作自然的整合到调用链中?br />
当然,以上仅仅是对奇?的一个过分简化的描述,它的实际功能要复杂得? 特别是有一个非常常用的直接构造功?
$("<table><tbody><tr><td>...</td></tr></tbody></table>")....
jQuery根据传入的html文本直接构造出一pd的DOM节点,q将其包装ؓjQuery对象. q在某种E度上可以看作是对selector的扩? html内容描述本n是一U唯一指定.
$(function{})q一功能实在是让h有些无语? 它表C当document.ready的时候调用此回调函数。真的,$是一个神奇的函数, 有Q何问题,?一下?br /> ȝh, $是从普通的DOM和文本描qC界到h丰富对象行ؓ的jQuery世界的跃q通道。跨q了q道门,来C理想国?br />
4. 无定形的参数Q专注表达而不是约?br /> q型语a既然头上着??? 总难免让人有些先天不的感觉. 在程序中~ZcdU束, 是否真的是一U重大的~憾? 在传l的强类型语a? 函数参数的类?个数{都是由~译器负责检查的U束条g, 但这些约束仍然是q远不够? 一般应用程序中Z加强U束, M增加大量防M性代? 例如在C++中我们常用ASSERT, 而在java中也l常需要判断参数值的范围
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
很显? q些代码导致程序中存在大量无功能的执行路径, x们做了大量判? 代码执行到某个点, pȝ抛出异常, 大喊此\不? 如果我们换一个思\, 既然已经做了某种判断,能否利用q些判断的结果来做些什么呢? javascript是一U弱cd的语a,它是无法自动U束参数cd? 那如果顺势而行,q一步弱化参数的形? ??推进CU极? 在弱无可q时? weak会不会成为标志性的特点?
看一下jQuery中的事gl定函数bind,
A. 一ơ绑定一个事?$("#my").bind("mouseover", function(){});
B. 一ơ绑定多个事?$("#my").bind("mouseover mouseout",function(){})
C. 换一个Ş? 同样l定多个事g
$("#my").bind({mouseover:function(){}, mouseout:function(){});
D. 想给事g监听器传点参?br /> $('#my').bind('click', {foo: "xxxx"}, function(event) { event.data.foo..})
E. 想给事g监听器分个组
$("#my").bind("click.myGroup″, function(){});
F. q个函数Z么还没有疯掉???
q是类型不定, 在固定位|上的参数的意义总要是确定的? 退一万步来说, q是参C|不重要?函数本n的意义应该是定的吧? 但这是什?
取?value = o.val(), 讄?o.val(3)
一个函数怎么可以q样q分, 怎么能根据传入参数的cd和个C同而行Z同呢? 看不眼是不? 可这是Z的hD. 既然不能防止, 那就故意允许. 虽然形式多变, 却无一句废? ~少U束, 不妨表?我不是出来吓人的).
5. 铑ּ操作: U性化的逐步l化
jQuery早期最主要的卖点就是所谓的铑ּ操作(chain).
$('#content') // 扑ֈcontent元素
.find('h3') // 选择所有后代h3节点
.eq(2) // qo集合, 保留W三个元?br /> .html('改变W三个h3的文?)
.end() // q回上一U的h3集合
.eq(0)
.html('改变W一个h3的文?);
在一般的命o式语a? 我们总需要在重重嵌套循环中过滤数? 实际操作数据的代码与定位数据的代码纠~在一? 而jQuery采用先构造集合然后再应用函数于集合的方式实现两种逻辑的解? 实现嵌套l构的线性化. 实际? 我们q不需要借助q程化的思想可以很直观的理解一个集? 例如 $('div.my input:checked')可以看作是一U直接的描述,而不是对q程行ؓ的跟t?
循环意味着我们的思维处于一U反复回l的状? 而线性化之后则沿着一个方向直U前q? 极大减轻了思维负担, 提高了代码的可组合? Z减少调用铄中断, jQuery发明了一个绝妙的L: jQuery包装对象本ncM数组Q集合). 集合可以映射到新的集合, 集合可以限制到自q子集合,调用的发赯是集合Q返回结果也是集合,集合可以发生l构上的某种变化但它q是集合, 集合是某U概念上的不动点Q这是从函数式语a中吸取的设计思想。集合操作是太常见的操作, 在java中我们很Ҏ发现大量所谓的装函数其实是在封装一些集合遍历操? 而在jQuery中集合操作因为太直白而不需要封?
铑ּ调用意味着我们始终拥有一?#8220;当前”对象Q所有的操作都是针对q一当前对象q行。这对应于如下公?br /> x += dx
调用铄每一步都是对当前对象的增量描qͼ是针Ҏl目标的逐步l化q程。Witrixq_中对q一思想也有着q泛的应用。特别是Z实现q_机制与业务代码的融合Q^C提供对象Q容器)的缺省内容,而业务代码可以在此基上进行逐步l化的修正,包括取消~省的设|等?br /> 话说回来, 虽然表面上jQuery的链式调用很? 内部实现的时候却必须自己多写一层@? 因ؓ~译器ƈ不知?自动应用于集合中每个元素"q回?
$.fn['someFunc'] = function(){
return this.each(function(){
jQuery.someFunc(this,...);
}
}
6. data: l一数据理
作ؓ一个js库,它必解决的一个大问题是js对象与DOM节点之间的状态关联与协同理问题。有些js库选择以js对象ZQ在js对象的成员变量中保存DOM节点指针Q访问时L以js对象为入口点Q通过js函数间接操作DOM对象。在q种装下,DOM节点其实只是作ؓ界面展现的一U底?#8220;汇编”而已。jQuery的选择与Witrixq_cMQ都是以HTML自nl构为基Q通过js增强(enhance)DOM节点的功能,它提升Z个具有复杂行为的扩展对象。这里的思想是非侵入式设?non-intrusive)和优雅退化机?graceful degradation)。语义结构在基础的HTML层面是完整的Qjs的作用是增强了交互行为,控制了展现Ş式?br /> 如果每次我们都通过$('#my')的方式来讉K相应的包装对象,那么一些需要长期保持的状态变量保存在什么地方呢QjQuery提供了一个统一的全局数据理机制?br /> 获取数据 $('#my').data('myAttr') 讄数据 $('#my').data('myAttr',3);
q一机制自然融合了对HTML5的data属性的处理
<input id="my" data-my-attr="4" ... />
通过 $('#my').data('myAttr')可以读取到HTML中设|的数据?br />
W一ơ访问dataӞjQueryؓDOM节点分配一个唯一的uuid, 然后讄在DOM节点的一个特定的expando属性上, jQuery保证q个uuid在本面中不重复?br /> elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
以上代码可以同时处理DOM节点和纯js对象的情c如果是js对象Q则data直接攄在js对象自n中,而如果是DOM节点Q则通过cachel一理?br /> 因ؓ所有的数据都是通过data机制l一理的,特别是包括所有事件监听函?data.events)Q因此jQuery可以安全的实现资源管理。在clone节点的时候,可以自动clone其相关的事g监听函数。而当DOM节点的内容被替换或者DOM节点被销毁的时候,jQuery也可以自动解除事件监听函? q安全的释放相关的js数据?br />
7. eventQ统一事g模型
"事g沿着对象树传?q一图景是面向对象界面编E模型的_N所在。对象的复合构成对界面结构的一个稳定的描述Q事件不断在对象树的某个节点发生Qƈ通过冒机制向上传播。对象树很自然的成ؓ一个控制结构,我们可以在父节点上监听所有子节点上的事gQ而不用明与每一个子节点建立兌?br /> jQuery除了Z同浏览器的事件模型徏立了l一抽象之外,主要做了如下增强:
A. 增加了自定制事g(custom)机制. 事g的传播机制与事g内容本n原则上是无关? 因此自定制事件完全可以和览器内|事仉过同一条处理\? 采用同样的监听方? 使用自定制事件可以增Z码的内聚? 减少代码耦合. 例如如果没有自定制事? 兌代码往往需要直接操作相关的对象
$('.switch, .clapper').click(function() {
var $light = $(this).parent().find('.lightbulb');
if ($light.hasClass('on')) {
$light.removeClass('on').addClass('off');
} else {
$light.removeClass('off').addClass('on');
}
});
而如果用自定制事g,则表辄语义更加内敛明确,
$('.switch, .clapper').click(function() {
$(this).parent().find('.lightbulb').trigger('changeState');
});
B. 增加了对动态创点的事g监听. bind函数只能监听函数注册到已经存在的DOM节点? 例如
$('li.trigger').bind('click',function(){}}
如果调用bind之后,新徏了另一个li节点,则该节点的click事g不会被监?
jQuery的delegate机制可以监听函数注册到父节点上, 子节点上触发的事件会Ҏselector被自动派发到相应的handlerFn? q样一来现在注册就可以监听未来创徏的节?
$('#myList').delegate('li.trigger', 'click', handlerFn);
最qjQuery1.7中统一了bind, live和delegate机制, 天下一l? 只有on/off.
$('li.trigger’).on('click', handlerFn); // 相当于bind
$('#myList’).on('click', 'li.trigger', handlerFn); // 相当于delegate
8. 动画队列Q全局旉协调
抛开jQuery的实C? 先考虑一下如果我们要实现界面上的动画效果, 到底需要做些什? 比如我们希望一个div的宽度在1U钟之内?00px增加?00px. 很容易想? 在一D|间内我们需要不时的去调整一下div的宽? [同时]我们q需要执行其他代? 与一般的函数调用不同的是, 发出动画指o之后, 我们不能期待立刻得到惌的结? 而且我们不能原地{待l果的到? 动画的复杂性就在于:一ơ性表达之后要在一D|间内执行,而且有多条逻辑上的执行路径要同时展开, 如何协调?
伟大的艾萨克.牛顿爵士在《自然哲学的数学原理》中写道:"l对的、真正的和数学的旉自n在流逝着". 所有的事g可以在时间u上对? q就是它们内在的协调? 因此Z从步骤A1执行到A5, 同时步骤B1执行到B5, 我们只需要在t1时刻执行[A1, B1], 在t2时刻执行[A2,B2], 依此cL.
t1 | t2 | t3 | t4 | t5 ...
A1 | A2 | A3 | A4 | A5 ...
B1 | B2 | B3 | B4 | B5 ...
具体的一U实现Ş式可以是
A. Ҏ个动? 其分装Z个Animation对象, 内部分成多个步骤.
animation = new Animation(div,"width",100,200,1000,
负责步骤切分的插值函?动画执行完毕时的回调函数);
B. 在全局理器中注册动画对象
timerFuncs.add(animation);
C. 在全局旉的每一个触发时? 每个注册的执行序列推进一? 如果已经l束, 则从全局理器中删除.
for each animation in timerFuncs
if(!animation.doOneStep())
timerFuncs.remove(animation)
解决了原理问?再来看看表达问题, 怎样设计接口函数才能够以最紧凑形式表达我们的意? 我们l常需要面临的实际问题:
A. 有多个元素要执行cM的动?br /> B. 每个元素有多个属性要同时变化
C. 执行完一个动M后开始另一个动?br />jQuery对这些问题的解答可以说是榨尽了js语法表达力的最后一点剩余h?
$('input')
.animate({left:'+=200px',top:'300'},2000)
.animate({left:'-=200px',top:20},1000)
.queue(function(){
// q里dequeue首先执行队列中的后一个函?因此alert("y")
$(this).dequeue();
alert('x');
})
.queue(function(){
alert("y");
// 如果不主动dequeue, 队列执行׃断了,不会自动l箋下去.
$(this).dequeue();
});
A. 利用jQuery内置的selector机制自然表达对一个集合的处理.
B. 使用Map表达多个属性变?br /> C. 利用微格式表N域特定的差量概念. '+=200px'表示在现有值的基础上增?00px
D. 利用函数调用的顺序自动定义animation执行的顺? 在后面追加到执行队列中的动画自然要等前面的动d全执行完毕之后再启动.
jQuery动画队列的实现细节大概如下所C?
A. animate函数实际是调用queue(function(){执行l束旉要调用dequeue,否则不会驱动下一个方法})
queue函数执行? 如果是fx队列, q且当前没有正在q行动画(如果q箋调用两次animate,W二ơ的执行函数在队列中等?,则会自动触发dequeue操作, 驱动队列q行.
如果是fx队列, dequeue的时候会自动在队列顶端加?inprogress"字符?表示要执行的是动画.
B. 针对每一个属性,创徏一个jQuery.fx对象。然后调用fx.custom函数(相当于start)来启动动甅R?br /> C. custom函数中将fx.step函数注册到全局的timerFuncs中,然后试图启动一个全局的timer.
timerId = setInterval( fx.tick, fx.interval );
D. 静态的tick函数中将依次调用各个fx的step函数。step函数中通过easing计算属性的当前|然后调用fx的update来更新属性?br /> E. fx的step函数中判断如果所有属性变化都已完?则调用dequeue来驱动下一个方法?br />
很有意思的? jQuery的实C码中明显有很多是接力触发代码: 如果需要执行下一个动d取出执行, 如果需要启动timer启动timer{? q是因ؓjsE序是单U程?真正的执行\径只有一?Z保证执行U烦不中? 函数们不得不互相帮助一? 可以惌, 如果E序内部h多个执行引擎, 甚至无限多的执行引擎, 那么E序的面貌就会发生本质性的改变. 而在q种情Ş? 递归相对于@环而言会成为更自然的描q?
9. promise模式Q因果关pȝ识别
现实?L那么多时间线在独立的演化着, Z物在时空中交?却没有发生因? 软g? 函数们在源代码中排着? 隑օ会生一些疑? 凭什么排在前面的要先执行? N没有它就没有? 让全宇宙喊着1,2,3齐步前进, 从上帝的角度?大概是管理难度过大了, 于是便有了相对论. 如果怺之间没有交换信息, 没有产生怺依赖, 那么在某个坐标系中顺序发生的事g, 在另外一个坐标系中看? 可能是颠倒顺序的. E序员依葫芦ȝ, 便发明了promise模式.
promise与future模式基本上是一回事,我们先来看一下java中熟悉的future模式.
futureResult = doSomething();
...
realResult = futureResult.get();
发出函数调用仅仅意味着一件事情发生过, q不必然意味着调用者需要了解事情最l的l果. 函数立刻q回的只是一个将在未来兑现的承诺(Futurecd), 实际上也是某种句柄. 句柄被传来传? 中间转手的代码对实际l果是什?是否已经q回漠不兛_. 直到一D代码需要依赖调用返回的l果, 因此它打开future, 查看了一? 如果实际l果已经q回, 则future.get()立刻q回实际l果, 否则会d当前的执行\? 直到l果q回为止. 此后再调用future.get()L立刻q回, 因ؓ因果关系已经被徏? [l果q回]q一事g必然在此之前发生, 不会再发生变?
future模式一般是外部对象d查看future的返回? 而promise模式则是由外部对象在promise上注册回调函?
function getData(){
return $.get('/foo/').done(function(){
console.log('Fires after the AJAX request succeeds');
}).fail(function(){
console.log('Fires after the AJAX request fails');
});
}
function showDiv(){
var dfd = $.Deferred();
$('#foo').fadeIn( 1000, dfd.resolve );
return dfd.promise();
}
$.when( getData(), showDiv() )
.then(function( ajaxResult, ignoreResultFromShowDiv ){
console.log('Fires after BOTH showDiv() AND the AJAX request succeed!');
// 'ajaxResult' is the server’s response
});
jQuery引入Deferredl构, Ҏpromise模式对ajax, queue, document.ready{进行了重构, l一了异步执行机? then(onDone, onFail)向promise中追加回调函? 如果调用成功完成(resolve), 则回调函数onDone被执行, 而如果调用失?reject), 则onFail被执行. when可以{待在多个promise对象? promise巧妙的地Ҏ异步执行已经开始之后甚臛_l结束之?仍然可以注册回调函数
someObj.done(callback).sendRequest() vs. someObj.sendRequest().done(callback)
callback函数在发出异步调用之前注册或者在发出异步调用之后注册是完全等L, q揭C出E序表达永远不是完全_? d在着内在的变化维? 如果能有效利用这一内在的可变? 则可以极大提升ƈ发程序的性能.
promise模式的具体实现很? jQuery._Deferred定义了一个函数队列,它的作用有以下几点:
A. 保存回调函数?br /> B. 在resolve或者reject的时L保存着的函数全部执行掉?br /> C. 已经执行之后, 再增加的函数会被立刻执行?br />
一些专门面向分布式计算或者ƈ行计的语言会在语言U别内置promise模式, 比如E语言.
def carPromise := carMaker <- produce("Mercedes");
def temperaturePromise := carPromise <- getEngineTemperature()
...
when (temperaturePromise) -> done(temperature) {
println(`The temperature of the car engine is: $temperature`)
} catch e {
println(`Could not get engine temperature, error: $e`)
}
在E语言? <-是eventuallyq算W? 表示最l会执行, 但不一定是现在. 而普通的car.moveTo(2,3)表示立刻执行得到l果. ~译器负责识别所有的promise依赖, q自动实现调?
10. extend: l承不是必须?br /> js是基于原型的语言, q没有内|的l承机制, q一直让很多深受传统面向对象教育的同学们耿耿于怀. 但承一定是必须的吗? 它到底能够给我们带来什? 最U朴的回{是: 代码重用. 那么, 我们首先来分析一下承作Z码重用手D늚潜力.
曄有个概念叫做"多重l承", 它是l承概念的超U赛亚h? 很遗憑来被诊断为存在着先天~陷, 以致于出C一U对于承概늚解读: l承是"is a"关系, 一个派生对?is a"很多基类, 必然会出现精分? 所以多重承是不好?
class A{ public: void f(){ f in A } }
class B{ public: void f(){ f in B } }
class D: public A, B{}
如果DcMA,B两个基类l承, 而A和BcM都实C同一个函数f, 那么DcM的f到底是A中的fq是B中的f, 抑或是A中的f+B中的f? q一困境的出现实际上源于D的基cA和B是ƈ列关p? 它们满交换律和l合? 毕竟,在概念层面上我们可能难以认可两个L概念之间会出C属关p? 但如果我们放松一些概念层面的要求, 更多的从操作层面考虑一下代码重用问? 可以单的认ؓB在A的基上进行操? 那么可以得C个线性化的结? 也就是说, 攑ּA和B之间的交换律只保留结合律, extends A, B ?extends B,A 会是两个不同的结? 不再存在诠释上的二义? scala语言中的所谓trait(Ҏ?机制实际上采用的是q一{略.
面向对象技术发明很久之? 出现了所谓的面向斚w~程(AOP), 它与OOP不同, 是代码结构空间中的定位与修改技? AOP的眼中只有类与方? 不知道什么叫做意? AOP也提供了一U类似多重承的代码重用手段, 那就是mixin. 对象被看作是可以被打开,然后L修改的Map, 一l成员变量与Ҏp直接注射到对象体? 直接改变了它的行?
prototype.js库引入了extend函数,
Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
是Map之间的一个覆盖运? 但很用, 在jQuery库中也得C延用. q个操作cM于mixin, 在jQuery中是代码重用的主要技术手D?--没有l承也没什么大不了?
11. 名称映射: 一切都是数?
代码好不? 循环判断必须? 循环和判断语句是E序的基本组成部? 但是优良的代码库中却往往找不到它们的t媄, 因ؓq些语句的交l会模糊pȝ的逻辑ȝ, 使我们的思想q失在疲于奔命的代码q踪? jQuery本n通过each, extend{函数已l极大减了对@环语句的需? 对于判断语句, 则主要是通过映射表来处理. 例如, jQuery的val()函数需要针对不同标{进行不同的处理, 因此定义一个以tagName为key的函数映表
valHooks: { option: {get:function(){}}}
q样在程序中׃需要到处写
if(elm.tagName == 'OPTION'){
return ...;
}else if(elm.tagName == 'TEXTAREA'){
return ...;
}
可以l一处理
(valHooks[elm.tagName.toLowerCase()] || defaultHandler).get(elm);
映射表将函数作ؓ普通数据来理, 在动态语a中有着q泛的应? 特别? 对象本n是函数和变量的容器, 可以被看作是映射? jQuery中大量用的一个技巧就是利用名U映来动态生成代? 形成一U类似模板的机制. 例如Z实现myWidth和myHeight两个非常cM的函? 我们不需?br /> jQuery.fn.myWidth = function(){
return parseInt(this.style.width,10) + 10;
}
jQuery.fn.myHeight = function(){
return parseInt(this.style.height,10) + 10;
}
而可以选择动态生?br /> jQuery.each(['Width','Height'],function(name){
jQuery.fn['my'+name] = function(){
return parseInt(this.style[name.toLowerCase()],10) + 10;
}
});
12. 插g机制Q其实我很简?nbsp;
jQuery所谓的插g其实是$.fn上增加的函数, 那这个fn是什么东?
(function(window,undefined){
// 内部又有一个包?br /> var jQuery = (function() {
var jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
}
....
// fn实际是prototype的简?br /> jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {... }
}
// 调用jQuery()是相当于new init(), 而init的prototype是jQuery的prototype
jQuery.fn.init.prototype = jQuery.fn;
// q里q回的jQuery对象只具备最基本的功? 下面是一pd的extend
return jQuery;
})();
...
// jQuery暴露为全局对象
window.jQuery = window.$ = jQuery;
})(window);
昄, $.fn其实是jQuery.prototype的简?
无状态的插g仅仅是一个函? 非常?
// 定义插g
(function($){
$.fn.hoverClass = function(c) {
return this.hover(
function() { $(this).toggleClass(c); }
);
};
})(jQuery);
// 使用插g
$('li').hoverClass('hover');
对于比较复杂的插件开? jQuery UI提供了一个widget工厂机制,
$.widget("ui.dialog", {
options: {
autoOpen: true,...
},
_create: function(){ ... },
_init: function() {
if ( this.options.autoOpen ) {
this.open();
}
},
_setOption: function(key, value){ ... }
destroy: function(){ ... }
});
调用 $('#dlg').dialog(options)? 实际执行的代码基本如下所C?
this.each(function() {
var instance = $.data( this, "dialog" );
if ( instance ) {
instance.option( options || {} )._init();
} else {
$.data( this, "dialog", new $.ui.dialog( options, this ) );
}
}
可以看出, W一ơ调?('#dlg').dialog()函数时会创徏H口对象实例,q保存在data? 此时会调用_create()和_init()函数, 而如果不是第一ơ调? 则是在已l存在的对象实例上调用_init()Ҏ. 多次调用$('#dlg').dialog()q不会创建多个实?
13. browser sniffer vs. feature detection
览器嗅?browser sniffer)曄是很行的技? 比如早期的jQuery?br /> jQuery.browser = {
version:(userAgent.match(/.+(?:rv|it|ra|ie)[/: ]([d.]+)/) || [0,'0'])[1],
safari:/webkit/.test(userAgent),
opera:/opera/.test(userAgent),
msie:/msie/.test(userAgent) && !/opera/.test(userAgent),
mozilla:/mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent)
};
在具体代码中可以针对不同的浏览器作出不同的处?br /> if($.browser.msie) {
// do something
} else if($.browser.opera) {
// ...
}
但是随着览器市场的竞争升, 竞争Ҏ之间的互相模仿和伪装DuserAgent一片? 加上Chrome的诞? Safari的崛? IE也开始加速向标准靠拢, sniffer已经起不到积极的作用. Ҏ检?feature detection)作ؓ更细_度, 更具体的手D? 逐渐成ؓ处理览器兼Ҏ的L方式.
jQuery.support = {
// IE strips leading whitespace when .innerHTML is used
leadingWhitespace: ( div.firstChild.nodeType === 3 ),
...
}
只基于实际看见的,而不是曾l知道的, q样更容易做到兼Ҏ?
14. Prototype vs. jQuery
prototype.js是一个立意高q的? 它的目标是提供一U新的用体验,参照Ruby从语aU别对javascriptq行攚w,q最l真的极大改变了js的面貌?, extends, each, bind...q些耳熟能详的概念都是prototype.js引入到js领域? 它肆无忌惮的在window全局名字I间中增加各U概? 大有谁先占坑谁有? 舍我其谁的气? 而jQuery则扣扣烦? q比较实用化的理念, 目标仅仅是write less, do more而已.
不过{待Ȁq的理想M者的命运往往都是壮志未酬w先? 当prototype.js标志性的bind函数{被吸收到ECMAScript标准中时, 便注定了它的没落. 到处修改原生对象的prototype, q是prototype.js的独门秘技, 也是它的ȝ. 特别是当它试图模仿jQuery, 通过Element.extend(element)q回增强对象的时? 是d被jQueryl带到沟里去? prototype.js与jQuery不同, 它L直接修改原生对象的prototype, 而浏览器却是充满bug, 谎言, 历史包袱q夹杂着商业阴谋的领? 在原生对象层面解决问题注定是一场悲? 性能问题, 名字冲突, 兼容性问题等{都是一个帮助库的能力所无法解决? Prototype.js?.0版本据说要做大的变革, 不知是要与历史决? 攑ּ兼容? q是l箋挣扎, 在夹~中求生.
]]>
cfg.set("bgColor.b",3.0);
cfg.set("lightEnabled",false);
t_float b = cfg.get("bgColor.b");
bool l = cfg.get("lightEnabled");
但是内部使用时支持直接的属性访问,便于~译器检查, 也提高运速度?br />
bool l = cfg.lightEnabled;
所qC++的类型系l能够偷Ld很多见不得h的勾当,因此便有了下面这个简易机制?br />
#define G_P(x) do{if(strcmp(name,#x) == 0) { value = x; return; } } while(0)
class _GConfig{
public:
bool lightEnabled;
t_float minX;
t_float maxX;
t_float minY;
t_float maxY;
_GConfig(){
// initialize all primitive members
memset(this,0,sizeof(_GConfig));
}
};
class GConfig: public _GConfig{
public:
GColor bgColor;
GConfig(){
}
_variant_t get(const char* name){
_variant_t value;
get(name,value);
return value;
}
void get(const char* name,_variant_t& value){
G_P(lightEnabled);
G_P(minX);
G_P(maxX);
G_P(minY);
G_P(maxY);
G_P(bgColor.r);
G_P(bgColor.g);
G_P(bgColor.b);
G_P(bgColor.a);
}
void set(const char* name, _variant_t value){
S_P(lightEnabled);
S_P(minX);
S_P(maxX);
S_P(minY);
S_P(maxY);
S_P(bgColor.r);
S_P(bgColor.g);
S_P(bgColor.b);
S_P(bgColor.a);
}
};
_variant_t是VC++?lt;comdef.h>中提供的对变体数据类型的装。用S_P和G_Pq样的宏可以q译器查变量名的正性?br />
]]>
开?OpenSource)软gY件演化创造了新的可能?商业友好的开源Y件可以被不同的公司自qq用于不同的业务,
因而可以参与到不同的局部演化过E中. 在应用的q程? 开源Y仉临着巨大的重构压?q往往是超了应用最q泛的封闭源码Y件包?,
有可能保持更快的演化速度. 而通过对开源Y件的回馈, 对开源Y件的改进可以传播到时I围跨度巨大的软g开发过E中. 而且Z源码的开放?
开发h员的知识交流也随之开放v? cL于Darwinq化? 我们可以说开源驱动了整个软g业界的共同进?co-evolution).
多年? Eric Raymond在著名的文章"大教堂和市集"?http://263.aka.org.cn/Docs/c&b.html,
提出了开源的工程价? 但其所x的重点仍然只是单个Y件如何在开源的模式下演? 从今天的观点看来, q篇战斗檄文已经昑־有些局促了.
开源所造就的巨大演化空间远q超了软g工程所能够提供? 开源Y件现在已l在商业开发领域站E了脚跟,也渐渐超了单个公司能够控制的范?
可以说开源Y件的发展是无可逆{? 我们已经不会也不应该再回复到原先的封闭世界中.
]]>
不能在标准的览器中预览. 可以说创造了一个JSF IDE的市? 但是q无疑是一个无聊的市场. 现在有一些备选的Ҏ, 如Facelets, 使得jsf可以采用属性语? 但是只要x仅仅Zq么一点小的修正所需要付出的开发量p以让人崩溃?br> JSF提供了组件别的事g响应机制Q因此似乎是AJAX应用的理惛_所Q但从Witrixq_的开发实跉|看,JSF对于AJAX的用是受限制的Q有着很大局限性的Q组件事件响应ƈ不一定要采取JSF那种体系l构Q?br> 从实现角度上_Zjsp tag可以说是JSF的致命弱点之一. jsp tag从设计之始就一直是未经q实践考量Q其设计无法支撑复杂的控件架? 特别是早期JSF与标准的JSP tag不能互通实际上是明昄设计~陷, 而且性能问题是内|在该设计中? 现在虽经多个版本的不断补? 但是Z兼容? JSP Tag负担q重, 它始l是Z文本处理模型Q实际上不可能有什么本质性的q步. JSP tag模型q分孱弱必然造成JSF设计中大量处理过E堆叠到界面对象层,更加剧了JSF的模型复杂度和性能瓉?实际上根据Witrixq_中tpl模板技术的设计l验Q大量界面构E是可以在模板层以直观的方式完成的,而不需要借助视图模型对象?br> 所有问题的一个集中体现就是增加一个新的JSFlgl对不是一件^凡的事情Q如果有一天这个问题可以得到解冻I那时的JSF从思想和实C都必然和现在的JSF有着本质性的区别Q?br>
]]>
<class
entity-name="test.DynamicEntity"
table="DYNAMIC_ENTITY"
>...</class>
此外, 也可以选择部分字D动态映到Map
<class ...>
<dynamic-component name="dynamicAttributes">
<property name="foo" column="FOO"/>
<property name="bar" column="BAR"/>
</dynamic-component>
</class>
在HQL语句中可以直接用o.dynamicAttributes.foo来访问foo属性,所有操作与普通属性相同?br /> Z实现hiberante映射模型的动态更斎ͼ我们首先需要实现sessionFactory的动态更新。目前hibernate的实现只允许从hbm文g重徏sessionFactory, xZ个sessionFactory替换原有的sessionFactory, 在用spring的情况下Q这需要对org.springframework.orm.hibernate3.LocalSessionFactoryBeanq行小的hack?br /> Z动态属性和普通属性同样对待,要求在操作实体对象属性的时候需要能够自动处理nested property, 即需要如下类似的ҎQentityDao.getProperty(entity,"dynamicAttributes.foo"), entityDao.setProperty(entity,"dynamicAttributes.foo", attrValue).
Z使得应用E序自动处理新增属性,要求E序是meta驱动的:当实体对象增加了一个属性时Q只需要修改meta文gQ即可完成对于该属性的增删Ҏ汇ȝ普通应用需求?img src ="http://www.tkk7.com/canonical/aggbug/59703.html" width = "1" height = "1" />
]]>
]]>
最qgoogle发布了Google Web Toolkit(GWT)开发包Q这是一U用java语言开发AJAX应用的开发框架。从技术上看,GWTq没有什么新鲜之处,cM的概念在多年之前已l有各种试了,q些试从未真正吸引到够的注意。GWT的优势也许在于提供了一套模拟工P另外可能在屏蔽browser的兼Ҏ和bug斚w做得更好一些,但是真正的技术思想q没有什么突? Ruby On Rails同样是试囑ְruby语言直接映射到前台程? 但是它通过一个通用的prototype.js库最化了ruby语言和js语言之间的区?在概念上要比GWT的java2js的compiler概念要更加新颖一? (http://mir.aculo.us/stuff/COR_20060413_RailsAjax.pdf)
对于web开发而言Q我总认发挥web的特Ԍ而不是把它约束到其他领域的开发模式上。js+dom+html文本所能做到的l构控制E度要远q超组件技术,我也从未发现学习java要比学习html要更加容易。也许对于某些对于web一无所知的java开发h员来_GWT有些意义Q也许GWT会特别适合于某些特定的领域Q但是作ZU通用的开发框Ӟ我ƈ不看好它?br />
]]>
/view.jsp?objectName=XXObject&objectEvent=XXEvent&otherArgs&tplPart=XXPart
其中objectName对应于后台的服务对象QobjectEvent参数映射到服务对象的ҎQview.jsp是对于后台对象进行渲染的模板面Q而tplPart参数可以指定只用模板的某一部分q行渲染。如果我们选择json.jsp或者burlap.jsp作ؓ渲染模板Q则可以退化到q回数据而不是内容的方式。在js中进行简单的装后我们可以通过如下方式q行q程调用Q?br /> new js.Ajax().setObjectName("XXObject").setObjectEvent("XXEvent").addForm("XXFormId").callRemote(callbackFunc);
它对应的urlh?br /> /json.jsp?objectName=XXObject&objectEvent=XXEvent&...
对于同样的后C务处理,我们可以自由的选择渲染模板Q则可以很自然的得到更多的处理方式,例如q回javascript代码来实现对于前台的回调?br />
]]>
上v锐道的Dorado框架L是一个基于构件技术的、面向B/S和多层架构体pȝweb应用开发^収ͼ
其前w称为Extra。从具体功能来看Q如果将其看作是一个全功能的web应用开发^収ͼ 那它现在的功能集昑־太单薄了一?
其主要部分还是提供了一些前台的界面控g, 其他如web框架部分,很像是struts的一个简化版Q没有什么特异之处?
Dorado的技术特Ҏ大量采用ajax技术来实现前台控g. 其前后台交互采用了自定义的基于xml格式的rpc方式, 而数据绑定用了xml数据?例如
<xml id="__datasetEmployee" >
<records>
<record isCurrent="true" state="none" >
<new>,~73~73~73~73~73,~68~68,~44~31~32,true,true,295113600000,2034.0,,</new>
</record>
</xml>
record内部使用的是DoradoU有的编?解码规则, 大概是ؓ了压~数据量?
从Dorado目前提供的界面来看还是比较丰富的,基本满了一般信息系l开发的需? 但是其可扩展性似乎ƈ不是很好.
它虽然号U是lg式开?但是其前台和后台引擎g都没有提供完善的lg模型支持, 只是实现了一些既定的界面lg而已.
1. 其前台的js函数中存在着大量针对数据cd的switch语句,g其所能够支持的控件类型已l内|在前台引擎? 如果我们要增加一U新的界面组件大概需要在各处修改引擎代码, ~Z一U抽象机?
2. 后台ViewModel模型g是想构造出一个Component架构? 但这个模型目前看h明显没有Echo2q样的组件模型精?
g~Z一U一致的lg重组机制. Dorado的ViewModel是有状态的, 通过RPC机制,
它实际上可以独立于系lweb层与前台控g交互.
3.
Dataset是Dorado中最重要的数据供体接? 从它所提供的方?getField,deleteRecord,
insertRecord, movePrev, moveNext, getPageSize{可以看?
q明显是l定C可分表格的数据模型? 实际上整个系l设计似乎都隐含假定了一个Table模型, 例如Validator接口中具有一个函?
ViewField getField(), q里明确假定了validate只能针对单个字段q行, 而不是属于某个整体组件的.
4. Dorado中所有组件的界面代码生成都是以程序方式进行的, 没有模板机制. 因而增加新的控件的实现? 需要在后台通过java代码输出一部分界面, 在前台通过js脚本动态更新界? 工作量相当大.
5. Dorado中界面输出应该是通过Outputter接口来进?
public interface Outputter{
public String getStartOutput(HttpServletRequest req, Object o)throws Exception;
public String getEndOutput(HttpServletRequest req, Object o) throws Exception;
}
q里一斚w与web层Ş成了l定Q另一斚w它必d内部完整的生成界面代码之后一ơ性传入response, q无疑加重了后台的内存压?
输出分成了StartOutput和EndOutput大概是ؓ了支持布局lg{容器类lg, 相当于是lg内部可以有一个洞, q与Jsp
Tag模型是匹配的, 但是q种方式很难以高效率实现界面上的l构融合.
7. Doradog没有直接提供lg的再装机制, 在现有组件中作局部修正往往需要通过代码方式来进?例如表格中的性别字段需要显C图片而不是文? 则需要在Column的onRefresh事g中写入下代码,
if (record.getValue("sex")){
cell.innerHTML = "<img src='images/man.gif'>";
}
else{
cell.innerHTML = "<img src='images/woman.gif'>";
}
q明昑ַl不是可配置的内容了. 如果我所需要增加的代码是一个复杂的lg, q里很难进行处理了.
6. Dorado的技术绑定在了IE览器上, 无法兼容其它览? q有些偏ȝ前的标准化方?
目前的快速开发^台的一个共同特Ҏ集中在单表的CRUD(Create Read Update Delete)?
可以快速完成单表或M表的增删Ҏ. q本也是正确方向,毕竟目前pȝ开发中的大量工作都是重复性的单劳?
但是一般系l设计中Z支持单表操作而在建模的时候引入了对表格模型过强的依赖, 大大降低了系l的可扩展?
另外现在一般weblg框架的设计往往是模仿桌面开发领域的lg模式Q?希望提供完全黑箱式的lg调用方式, q其实是攑ּ了web开发的优势.
实际上借助于xml格式的规范性和单? 我们完全可以提供更加强大的结构组? q把lg装的能力开攄普通程序员.
]]>
同方q个公司在我的印象中更像是个pȝ集成商,在Y件方面没有什么独特之处。不知道是否是待遇问题,我也未听说同Ҏ下招揽过什么Y仉手。同Ҏq两q?
在Y件^台方面花了一些气力,据说?0多个人,q了一两年Q将同方以前的项目进行提|开发了ezOneq_。现在同方各个事业部开发新目的时候好?
要求使用该^収ͼ不过可能是涉及到总部和各个部门分q问题Q下面的人未必有很大的应用积极性?br />
同方的特Ҏ做过大量目Q行业经验多Q所以ezOne中提供了很多行业lg。ezOne的一个核心部分是portal服务器,是基于Apache目l?
的Jetspeed修改而来Q应该是W合JSR168标准的,所的概念也正是应用集成。以前扫q一眼ezOne的代码,感觉质量一般,性能可能会有一
些问题,但编码还工整。同Ҏ有大量国家资源,应该不至于成为^C品开发商Q开发^台的目的大概q是降低自n开发的隑ֺ。其产品們于符合标准,中规
中矩Q大概很难有什么创C处。ezOne中很多基lg都是独立开发的Q例如存储层Q没有用hibernate{开源Y件?br />
web开发很大一部分工作是建立q两个结构之间的关系。即我们需?br> html <--> java
?
们首先要意识到这两种l构之间q不一定是同构的,卛_台数据的l织方式与前台展现时的结构是不同的。同L数据可以对应于不同的展现l构。这也是所?
MVC架构实现模型与视囑ֈȝ依据。传l上Q基于Model2模式的MVC框架中,q两U结构的映射只能在很_的_度上进行(x个页面的_度上)Q因
此妨了装和重用。ؓ了进行细_度的映,我们必须要拥有细_度的结构控制能力。而目前最强的l构控制能力存在于javascript/DHTML模型
之中Q在js中html的结构可以是一D늺性的文本(innerHTML和outerHTML), 可以是层U组l的节点QparentNode,
childNodes),
也可以是按照keyl织h的Map(getElementById)。在不同的情形下Q我们可以根据需要选择不同的结构模型?br>
ajax体系很直接的一个想法就是将所有关于界面表辑֒控制的结构都推到前台Q由控制力最强的js来控制后台数据模型与前台html模型之间的映?br>
html <--> js <==> xml <==> java
在ajax
体系中,xml所扮演的角色是js与java之间的翻译通道Q它js中的l构与java中的l构对应hQ这U翻译比html/java之间的映要
单的多。其实它甚至可以是一U同构的映射Q可以用一U通用的方式来q行Q例如结合burlap与buffalo包的功能。结合webservice的一?
思想Qjs/java之间的映是可以在函数调用这U细_度上自动进行的Q从而我们最l可以在概念上完成html/java之间的细_度映射?/p>
public void testMy(){
MyObject my = new MyObject();
Object value = myObject.myFunc();
Debug.check(value.equals("aa"));
// 可以同时提供一个出错消?br>
Debug.check(value.equals("aa"),"myFunc return invalid : "+value);
}
public static void main(String[] args){
// 不需要IDE或者其他外部的支持可以直接调用测试代码,会自动输出q行旉{?br>
UnitTest.exec(new MyTest("testMy"));
}
}
cocoon使用道技术也构造了某种tag机制Q但是它的效率很成问题。从数学上说多个处理函数 g, h, k可以通过函数l合(composition)构成新的函数f
f(data) = g * h * k(data)
q是所谓函数式语言强大能力的源泉。cocoon处理的时候从k(data)开始,处理完毕之后调用h, 卛_数是从右向左l合的。如果我们保证处理函数满_l合律,则g*h*k可以预~译为f, 从而解x能问题Q这正是witrixq_中tpl技术所采用的方案?/p>
Scheduler接口: quartz的执行线E,它根据Trigger军_调度时刻Q根据JobDetail的说明实例化q运行Job
JobDetailc? 可持久化的Q务描qC息。Q务虽然分l,但是仅用作管理标C,d之间q无实质性关? 例如无法定义job chain?br>
Triggerc?d的调度策略。这里的特点是调度策略与d描述分开Q调度策略和d描述都可以分别在Scheduler注册Q然后再兌h。JobDetail与Trigger的关pL一对多?br>
JobDataMap: Q务的q行时可持久化状态信息从JobDetailcM分离出来
Job接口: d的执行代?br>
StatefulJob接口: 无状态Q务对应的JobDataMap可以认ؓ是只ȝ,而有状态的d在多ơ执行过E中保留对JobDataMap所作的修改,一个后果是有状态Q务无法被q发执行?br>
JobExecutionExceptionc? 可以通过JobExecutionException调整调度E序的下一步动?br> Calendar接口: 用于从trigger的调度计划中排除某些旉D,例如假期{?/p>
以上几个部分的交互关pd下:
class JobImpl implements Job{
public void execute(JobExecutionContext context) throws JobExecutionException{
JobDetail detail = context.getJobDetail();
JobDataMap dataMap = detail.getJobDataMap();
...
}
}
scheduler.addCalendar("myHolidays", holidayCalendar, false);
trigger.setCanlendarName("myHolidays");
JobDetail jobDetail = new JobDetail(jobName, jobGroupName, JobImpl.class);
scheduler.scheduleJob(jobDetail, trigger);
JobDetail可以讄如下属?
1. Durability: non-durable的Q务当不再与Q何active trigger兌的时候将会从scheduler中被自动删除?br>
2. Volatility: volatile的Q务在scheduler的两ơ启动之间不会被持久?br>
3. RequestsRecovery: 如果在执行过E中E序意外崩溃Q标Cؓ"request recovery"的Q务在scheduler重v之后会被再ơ执行,此时JobExecutionContext.isRecovering()q回true.
Trigger可以讄如下属?
1. misfireInstruction: 讑֮当trigger错过了触发时ȝ时候需要采取的处理{略
SimpleTrigger按照固定的时间间隔进行触?br> startTime, endTime, repeatCount, repeatInterval
CronTrigger按照日历间隔q行触发
seconds minutes hours day-of-month month day-of-week
在quartz内部QQuartzSchedulerThread按照旉序选择triggerQ没有Q务优先的概念), 然后在JobRunShell中运行Job?/p>
JobRunShell中的调用序如下:
TriggerListener.triggerFired
Called by the Scheduler when a Trigger has fired, and it's associated JobDetail is about to be executed.
TriggerListener.vetoJobExecution
Called by the Scheduler when a Trigger has fired, and it's associated JobDetail is about to be executed.
JobListener.jobToBeExecuted
Called by the Scheduler when a JobDetail is about to be executed (an associated Trigger has occured).
Job.execute
Called by the Scheduler when a Trigger fires that is associated with the Job.
JobListener.jobWasExecuted
Called by the Scheduler after a JobDetail has been
executed, and be for the associated Trigger's triggered(xx) method has
been called.
Trigger.executionComplete
Called after the Scheduler has executed the
JobDetail associated with the Trigger in order to get the final
instruction
code from the trigger.
TriggerListener.triggerComplete
Called by the Scheduler when a Trigger has
fired, it's associated JobDetail has been executed, and it's
triggered(xx)
method has been called.
SchedulerListener.triggerFinalized [if(trigger.getNextFireTime() == null)]