2006年01月18日

英文原文:http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html

JDK5.0 引入了一种新的元语言工具,叫“annotation”。 Annotation 提供的信息不是程序的一部分,例如,代码片断的作者,或者告诉编译器忽略特定的错误等。Annotation不会对程序的运行产生任何影响。

Annotation的形式为:@annotation。它可以被应用到类,属性,方法等的声明处。Annotation位于他们之前,并且(通常)独立一行。它还可以带有参数,例如:
    @Author("MyName")
    class myClass {}
或者
    @SuppressWarnings("unchecked")
    void MyMethod() {}

自定义annotation属于高级用法,不属于本文讨论范畴。但是有三个内置的annotation你必须知道(如果你是Java程序员的话),他们是@Deprecated,@Override和@SuppressWarnings。以下列举他们对于方法的应用。

import java.util.List;

class Food {}
class Hay extends Food {}
class Animal {
Food getPreferredFood() {
return null;
}
/**
* @deprecated document why the method was deprecated
*/
@Deprecated
static void deprecatedMethod() { }
}
class Horse extends Animal {
Horse() {
return;
}
@Override
Hay getPreferredFood() {
return new Hay();
}
@SuppressWarnings("deprecation")
void useDeprecatedMethod() {
Animal.deprecateMethod(); //deprecation warning - suppressed
}
}

@Deprecated

@Deprecated annotation 表示被标志的方法不应该被继续使用了,如果程序使用了deprecated的类,变量或方法,编译器将会给出警告。如果一个元素被deprecate了,那么应该如上例所示在上面的注释文档中添加deprecated的标记并给出原因。注意,文档中标记的首字母是小写d,annotation中的首字母是大写D。一般来说,你应该避免使用deprecated的方法,可以参阅相关文档了解替代方法。


@Override

@Override annotation是为了告诉编译器,该元素会override父类的这个元素。在上例中,override annotation表示Horse中的getPreferredFood方法将会override 父类Animal中的getPreferredFood方法。如果这步失败,编译器会报错。

尽管Override的时候并不是必须使用这个annotation,使用它还是可以使程序逻辑更明了化,特别是当子类方法的返回值继承自父类方法的返回值。如在上例中,子类的getPreferredFood方法返回Hey的实例,父类的getPreferredFood方法返回Food的实例,其中Hey继承Food。更多信息见Overriding and Hiding Methods


@SuppressWarnings

@SuppressWarnings告诉编译器,此处不要报错。在上例中,useDeprecatedMethod方法调用了Animal类中的deprecated方法,通常编译器会给出警告,但是此处,被suprress了。

每一个编译器警告属于一个类别,Java语言规范中列出了两类:“deprecation” 和“unchecked”。如果要suppress这两类警告,使用如下方式:
    @SuppressWarnings ( {"unchecked", "deprecation"} )
参见编译器文档了解警告的类别。

对于annotation更高级的用法是写一段程序不仅可以读java代码,并且可以处理annotations。为了达到这个目标,5.0JDK中包含了一个处理annotation的工具,称为apt。下一个版本JDK(代号Mustang)的apt将成为Java编译器的一个标准部分。更多信息,可以参见Getting Started with the Annotation Processing Tool。关于正在实现的Mustang感兴趣,可以参见Language Model APIJSR 269: Pluggable Annotation Processing API

2006年01月16日

英文原文出自《Spring In Action》

像绝大多数的技术一样,AOP也有自己的术语。不幸的是,很多用于描述AOP特征的术语并不直观,但是,它们已经成为了AOP语言的一部分,如果你想理解AOP,你必须学会这门AOP语言。通俗地说,你想在圈子里面混,你就得学会说行话。

Aspect

Aspect是你正在实现的一个cross-cutting的功能,它是你应用中正在模块化的一个方面(aspect)。比较通用的一个例子是日志。记录日志是一项贯穿整个应用的服务。由于应用基本以功能(基于业务逻辑)为界限进行划分模块,故通过继承的方法来重用日志模块似乎不合理。但是,你可以创建一个日志aspect来实现你的想法。

Joinpoint

Joinpoint是在应用运行中那些aspect可以插进来的点。这个点可能是一个被调用的方法,一个被抛出的异常,甚至可以是一个被改变的字段。在这些点处添加你的aspect的代码,就可以为你的应用增加一些新的行为。

Advice

Advice是对aspect的一个具体实现。它向系统建议(advice)增加一个新的行为。在我们的日志例子中,日志advice包含了记录日志的代码并实现真正的日志记录,比如将日志写入文件。Advice被添加到joinpoint点上。

Pointcut

Pointcut定义了advice应该被插入到什么样的joinpoint点上。Advice可以被应用到任意AOP框架支持的joinpoint上。当然,你不会希望将所有的aspect应用到可以被应用的joinpoint上面。Pointcut让你可以指定advice应用的位置。通常,你用具体的类名或方法名,或者一些符合表达式的类或方法名来指定pointcut。 一些AOP框架允许你创建动态的pointcuts,这些pointcuts可以在运行的时候动态决定是否需要应用advice,比如方法的参数值。

Introduction

Introduction可以让你添加方法和属性到已经存在的类中。例如,你可以创建一个Auditable的advice类用来跟踪某对象最后改变的时期。这个可以简单地通过一个属性记录状态,并添加一个setLastModified(Date)方法来实现。然后,它可以被引入(introduce)到已经存在的类。这样,已有的类不需要做任何改变就有了个新的功能。

Target

Target是正在被advice的类,这可以是你自己写的一个类或者是你想增加新的功能的第三方提供的类。没有AOP,这个类必须被包括自身主要的逻辑并且额外加上那些cross-cutting关心的逻辑。有了AOP,target类只需要关注自身所需要关心的,而把那些应用于自身的advices抛到脑后。

Proxy

Proxy是被应用了advice的target实例。从客户实例的角度来看,无论是target实例(AOP之前)还是proxy实例(AOP以后),都是一样的,当然,它们本来就应该是一样的。也就是说,你的既有应用不需要做改变来支持proxy类。

Weaving

Weaving是指把aspects应用到目标实例上去创建一个新的proxied实例的过程。Aspects在目标对象的joinpoint被组合(weave)进去。Weaving可以发生在目标类生存的如下时间:

  • 编译期 — Aspects在目标类编译期被weave。这个需要特殊的编译器。
  • 载入期 — Aspects在目标类载入期被weave。这个需要特殊的类装载器。
  • 运行期 — Aspects在应用运行时的某个时期被weave。一般来说,AOP容器在weave in aspects的时候会动态创建proxy类来代理target类。

图例:

PS:

2006年01月14日

英文原文:http://getahead.ltd.uk/dwr/browser/util

util.js 包含了一系列的方法帮助你通过javascript对象更新Web页面(比如从服务器端返回的结果对象)。

util.js是一个很独立的模块,可以脱离DWR使用,你可以直接下载,或者和DWR一起下载

四个基本的页面操作函数:getValue[s]()和setValue[s]()对于绝大多数的HTML元素都有效,除了表格(tables), 列表(lists) 和图片(images). getText() 作用于select lists。

编辑表格可以参见addRows()removeAllRows()。编辑列表(包括select lists and ul, ol lists),参见addOptions()removeAllOptions()

下一页

英文原文: http://getahead.ltd.uk/dwr/server/dwrxml

dwr.xml文件可以存在多个(详见web.xml说明文档)。每个文件里面的条目会被结合在一起。DWR据此调用到每一个条目来确保他们的启动。

我们可以通过分析这个标准的dwr.xml来了解它的概貌。


DWR DTD

除去本文外,有关dwr.xml的资料还可以参考DWR DTD和由DTDDoc生成的相关文章


创建一个dwr.xml文件

每一个dwr.xml文件都必须包括DWR DOCTYPE,如下所示:

<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">

以下是一个dwr.xml文件的概貌:

<dwr>

<init>
<creator id="..." class="..."/>
<converter id="..." class="..."/>
</init>

<allow>
<create creator="..." javascript="..." scope="...">
<param name="..." value="..."/>
</create>

<convert converter="..." match="..."/>
</allow>

<signatures>
...
</signatures>

</dwr>

一些必须事先弄清的概念是 – 参数是被转换的(converted),而beans是被创建的(created)。所以,如果你有一个bean A,并且A有一个方法A.blah(B),那么,你需要bean A的creator 和B的converter

init部分是可选的,它用来声明那些需要创建的bean和转换的类。大多数情况,你不需要它。如果你需要定义一个新的Creator[JavaDoc]或者Converter[JavaDoc],那么,可以在此声明,但请确认这个Creator或Converter没有被定义过。

init给出的信息只是告诉DWR存在某些类,但并没有使用它们。这有点像Java语言中的import。外部类必须先import然后才能使用,但是import并不意味着肯定会使用它们。init中的creator或converter都有一个id属性以供使用时引用。

allow部分通过create和convert结点定义了DWR可以创建(create)和转变(convert)的类。以下类默认已经作好转化,可以直接使用,不用声明:

  • 所有的基本类型,布尔(boolean),整型(int)等
  • 所有上述基本类型的封装类,布尔(Boolean),整型(Integer)等
  • 字符串(String)类
  • 日期(java.util.Date)类和三个SQL派生的
  • 由上述类型组成的数组
  • 由上述类型组成的集合(Lists, Sets and Maps),有一定限制

然而,如果要创建(create)一个类,则必须先声明。

2006年01月08日

在学生时代,学校有一个经常被传颂的口号是“培养德智体全面发展的优秀学生”。

德智体,此处只谈智。谈智的时候,对应一下体。

在过去的时代,对于一个人来说,体所需要占的比重比较大,人们对于智的要求不是很高。由于非脑力劳动的工作大多将被机器所取代,而无法被取代的,恰是需要用到人智力的,故在现今,情况可能正好相反。而从事纯脑力劳动者,对智力的要求更是显而易见的,说得更直接和一般化点,脑力劳动者“卖”的不是人,而是他们的 智力。 对于毕业生找工作,公司多数会看文凭,因为没有更多的可以反映智力的地方。那次高考,也可以被认为是一次智力的测试。我想,不可否认,在不了解对方的大多数情况下,通过文凭还是基本能区分智力的高低的。(填鸭式的教育和题海战术会使这种判断丧失准确性,故从某种程度来说,这种教育本身是一种作弊)

我们从小被教育要刻苦读书,并被灌以“头悬梁,锥刺骨”的痛苦却极为正面的印象,殊不知,那恰是“笨鸟先飞”的真实写照。因为有了足够的智力,才能过了那次高考,而不是因为过了高考,大幅提高了自己的智力。

这样说来,似乎有些悲观。

由于体的发展已经到了一个比较成熟的阶段,我们来看看体。体力方面的工作,需要体力强的人,体的判断比较容易,并且观念已经被大多数人所接受,所以,没有一个类似于高考之类的东西,仅在学校的时候有一个叫“达标”的标准。体方面的培养,也很纯粹,通过各种各样的体育锻炼和健身运动提高自己的体。

智力会提高或者降低吗?读书时语文课本里的一篇《伤仲永》,很好的以例子回答了这个问题。其实智力和体力一样,是可以通过锻炼而提高的。我们在学习的过程中,都在提高自己的智,也许目的性不强或并不直接。

智的提高,周期较长且不易考量,所以容易被忽略和被一些近利的观念所遗弃,然而,锻炼智力,开发智力,培养思维,比抱着一本书去应付考试更为重要。

如果有一天,人们对于智的观念转变了,那么,基于一个庞大的市场,也许就会有各种各样的健脑房或由此而衍生的新的游戏,智力的开发也将更为系统和详细。


P.S. 德智体,也许古人对于词的排列顺序都有考究,不知道何时,德才能真的站在第一的位置上。

2006年01月04日



  [Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]

上面的代码显示了两个类似的例子,类似的原因是为了易于发现区别。从代码看,在第一个例子中,鼠标移上那个层,显示字体会变红,第二个例子中,初始就是红色。只要触发了onmouseout事件,相应层所显示的字体就会变黑。

这些都是可以读懂的。不可理解的是,在第二个例子的时候,当鼠标移入Input框的时候,触发了onmouseout事件,而在第一个例子中没有。按照对onmouseout的理解,应该只有移出div层,才会触发,但是为什么在第二个例子中,明明是移入层内的一个元素,也算mouseout了呢?

对这个问题依旧疑惑,但是,却发现了第一个例子这样的解决方案,即写上mouseover。看上去,onmouseover对于层边界的理解要和我更贴近一些。呵呵。

更正: 以上两个例子里面,其实当鼠标移至input框中,都会触发onmouseout。在第一个例子中,只是因为onmouseover也持续触发,所以掩盖了层字体变黑这个情况。可以用alert再试下。这样,对于以上两个例子的表现基本可以解释了。查阅了一下相关资料,对于两个事件分别定义为:

The onmouseover event occurs when the pointing device is moved onto an element. This attribute may be used with most elements.

The onmouseout event occurs when the pointing device is moved away from an element. This attribute may be used with most elements.

从上面的定义来看,onmouseover和onmouseout指的都是an element,边界应该一样,然而实际情况是,他们对于an element的边界划分明显是不一样的。

2005年12月28日

我们总是用目光短浅,急功近利来贬低那些只注重眼前利益,没有大局观的想法或做法。

作网站的,都会知道Alexa排名(假设以下提到的网站在Alexa排名上都没有作弊),看一下如下的Traffic图。
77q8





他们有些共性,就是有一个明显的小山状曲线,并且时间相近。再看另外一些图



他们的特点是一直在上升,并且斜率不大。

以上只是Alexa排名的一个属性,如果纵轴表示的是利润,似乎很符合中国的一些名言警句。具体问题具体分析,那个短时间内迅速上窜的曲线,必定是有一个或一些诱因的。如果此因一旦消失,那么,由此上升的曲线必然会回到原始的波澜不惊。而如果曲线很陡,也说明这个高度可以在较短时间内达到,若“因”的复杂度不高,便会有趋之若鹜的效仿。抗风险性不够,简言之,就是来得容易,可能去得也不难。相比较,那些经过时间检验的网站,就不会有如此陡峭的下降曲线了。

那是否意味着近利皆不可图?如果别人用五到十年实现的目标,你可以用一个月实现,为什么不呢?只是为了保持曲线的持续递增,可能需要考虑引入新的诱因,或者增加原有诱因的稳定性,以至少维持曲线的水平。


2005年12月27日

最近学习Javascript,有点焦头烂额。所以,先做个笔记,以后补充。

变量有两种作用域,一个是全局 (Globle),一个是局部 (Local).

下文摘自“http://www.mredkj.com/tutorials/reference_js_intro.html#scope

===============================================

Global
A variable that is declared outside any functions is global. This means it can be referenced anywhere in the current document.

  • Declared outside any functions, with or without the var keyword.
  • Declared inside a function without using the var keyword, but only once the function is called.

Local
A variable that is declared inside a function is local. This means it can only be referenced within the function it is declared.

  • Declared in a function with the var keyword.

Other notes

If a variable is declared inside a conditional statement, it is still available anywhere following the declaration in the containing function (or globally if the conditional is not in a function). However, it will equal undefined if the condition evaluates to false, unless the variable is later assigned a value.

If a local variable is referenced globally or in another function, a JavaScript error will occur. Depending on your browser, the error may say the variable "is not defined" or "is undefined". This is different from the variable equaling undefined like I mentioned above, because a variable that equals undefined can still be referenced.

===============================================

根据上文前两块的定义,全局和局部变量还是相对比较容易区分,唯一一个需要注意的地方就是Function中的非var变量,只有在被调用后才是全局的。

  function test() {
   g="g";
  }
  test();
  alert(g);

如上例,只有在test被调用以后,g变量才是全局的,否则,是undefined。

Other notes里面的东西听起来有点匪夷所思,但是,写了一些小的测试代码以后,发现的确如此,所以也需要注意。

2005年12月21日

读了一段时间的blog,有空没空的时候也曾经写过几笔,终因江山易改,本性难移,最终一一作罢,临近年末,经常被一些诸如“盘点”样的字眼所刺激,掐指
算来,本年度不说浑浑噩噩,充其量也就算是个半梦半醒,幸运的是,梦的时候梦到了月老,醒的时候见到了嫦娥,算是本年度最佳意外收获。一个朋友对我说,
She could bring you out of your
shell。他应该没有说错,否则我也不会选择试写blog。写blog的好处有很多,之于我,最大的莫过于治治自己的懒病,哈,动机不纯。看看我能坚持
多久吧。

前些天一个机会去吃生煎,一两四只,我要了二两。边吃的时候,边想,两这个单位在这里究竟是用来做什么的呢?难道我要二两,他会
给我称吗?既然约定好了一两四只,那么直接说几只不是更容易理解吗?何必多一道“工序”?琢磨了半天,觉得两在这里存在的唯一价值是杜绝五,七这样的数字
而出现的。仅此而已吗,如果的确如此,是否有更简便的方法呢?

我是“IT人士”(汗),因为职业病的关系难免会联想到IT方面。代码编写
者,架构设计者,都希望自己的努力化作令自己满意的作品,于是乎,博览了设计模式,高质量代码等先辈心血结晶后的执行者们,手气刀落,雕刻出自认为鬼斧神
工的作品,仰视许久。这些先辈的心血的确是大补丸,可以修炼内功,但是,捉兔子的时候用乾坤大挪移,切葱的时候请来庖丁,又是否显得过于罗嗦?

我很懒,所以,我喜欢Nike的标志。

我很懒,所以,我喜欢用Google搜索。

我很懒,所以,我想把麻烦的事情简单化,这样可以美其名曰:简单就是一种美。