posts - 37,comments - 7,trackbacks - 0
http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-ajax/index.html?S_TACT=105AGX52&S_CMP=techcsdn
posted @ 2006-09-07 13:42 Dave 阅读(158) | 评论 (0)编辑 收藏
http://www.sergiopereira.com/articles/prototype.js.html
posted @ 2006-08-10 15:06 Dave 阅读(208) | 评论 (0)编辑 收藏
http://blog.csdn.net/calvinxiu/archive/2006/08/08/1036306.aspx
posted @ 2006-08-10 13:02 Dave 阅读(173) | 评论 (0)编辑 收藏
http://java.csdn.net/n/20060807/93375.html
posted @ 2006-08-10 13:01 Dave 阅读(185) | 评论 (0)编辑 收藏
http://java.csdn.net/n/20060808/93473.html
posted @ 2006-08-10 12:59 Dave 阅读(269) | 评论 (0)编辑 收藏
https://compdoc2cn.dev.java.net/prototype/html/prototype.js.cn.html
posted @ 2006-08-10 12:50 Dave 阅读(196) | 评论 (0)编辑 收藏
定义:一个正则表达式,就是用某种模式去匹配一类字符串的一个公式。
正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,我们下面会给予解释。

元字符 描述


.
匹配任何单个字符。例如正则表达式r.t匹配这些字符串:ratrutr t,但是不匹配root。 
$
匹配行结束符。例如正则表达式weasel$ 能够匹配字符串"He's a weasel"的末尾,但是不能匹配字符串"They are a bunch of weasels."。 
^
匹配一行的开始。例如正则表达式^When in能够匹配字符串"When in the course of human events"的开始,但是不能匹配"What and When in the"。
*
匹配0或多个正好在它之前的那个字符。例如正则表达式.*意味着能够匹配任意数量的任何字符。
\
这是引用府,用来将这里列出的这些元字符当作普通的字符来进行匹配。例如正则表达式\$被用来匹配美元符号,而不是行尾,类似的,正则表达式\.用来匹配点字符,而不是任何字符的通配符。
[ ] 
[c1-c2]
[^c1-c2]
匹配括号中的任何一个字符。例如正则表达式r[aou]t匹配ratrotrut,但是不匹配ret。可以在括号中使用连字符-来指定字符的区间,例如正则表达式[0-9]可以匹配任何数字字符;还可以制定多个区间,例如正则表达式[A-Za-z]可以匹配任何大小写字母。另一个重要的用法是“排除”,要想匹配除了指定区间之外的字符——也就是所谓的补集——在左边的括号和第一个字符之间使用^字符,例如正则表达式[^269A-Z] 将匹配除了2、6、9和所有大写字母之外的任何字符。
\< \>
匹配词(word)的开始(\<)和结束(\>)。例如正则表达式\<the能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。
\( \)
将 \( 和 \) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1\9 的符号来引用。
|
将两个匹配条件进行逻辑“或”(Or)运算。例如正则表达式(him|her) 匹配"it belongs to him"和"it belongs to her",但是不能匹配"it belongs to them."。注意:这个元字符不是所有的软件都支持的。
+
匹配1或多个正好在它之前的那个字符。例如正则表达式9+匹配9、99、999等。注意:这个元字符不是所有的软件都支持的。
?
匹配0或1个正好在它之前的那个字符。注意:这个元字符不是所有的软件都支持的。
\{i\}
\{i,j\}
匹配指定数目的字符,这些字符是在它之前的表达式定义的。例如正则表达式A[0-9]\{3\} 能够匹配字符"A"后面跟着正好3个数字字符的串,例如A123、A348等,但是不匹配A1234。而正则表达式[0-9]\{4,6\} 匹配连续的任意4个、5个或者6个数字字符。注意:这个元字符不是所有的软件都支持的。


posted @ 2006-08-07 17:06 Dave 阅读(162) | 评论 (0)编辑 收藏
public aspect TraceAspect{
   private Logger _logger = Logger.getLogger("trace");
   pointcut traceMethods(): execution(* *.*(..))&&!within(TraceAsptect);
   before() : traceMethods(){
      Signature sig = thisJoinPointStaticPart.getSignature();
      _logger.logp(Level.INFO, sig.getDeclaringType().getName(), sig.getName(), "Entering");
  }
}

What’s wrong with conventional logging ?

When a new module is added to the system, all of its methods that need logging must be instrumented. Such instrumentation is invasive, causing the tangling of the core concerns with the logging concern. Further, if you ever happen to change the logging toolkit to a different API, you need to revisit every logging statement and modify it.

Consistency is the single most important requirement of logging. It means that if the logging specification requires that certain kinds of operations be logged, then the implementation must log every invocation of those operations. When things go wrong in a system, doubting the logging consistency is probably the last thing you want to do. Missed logging calls can make output hard to understand and sometimes useless. Achieving consistency using conventional logging is a lofty goal, and while systems can attain it initially, it requires continuing vigilance to keep it so. For example, if you add new classes to the system or new methods in existing classes, you must ensure that they implement logging that matches the current logging strategy.

The beauty of AspectJ-based logging

The limitations are not a result of the logging APIs or their implementations; rather, they stem from the fundamental limitations of objectoriented programming, which require embedding the logging invocations in each module. AOP and AspectJ overcome those limitations. AspectJ easily implements the invocation of logging statements from all the log points. The beauty is that you do not need to actually instrument any log points; writing an aspect does it automatically. Further, since there is a central place to control logging operations, you achieve consistency easily.

The most fundamental difference between conventional logging and AspectJbased logging is modularization of the logging concern. Instead of writing modules that implement core concepts in addition to invoking logging operations, with AspectJ you write a few aspects that advise the execution of the operations in the core modules to perform the logging. That way, the core modules do not carry any logging-related code. By modularizing, you separate the logging concern
from the core concerns.

With AspectJ-based logging, the logger aspect separates the core modules and the logger object. Instead of the core modules’ embedding the log() method invocations in their source code, the logger aspect weaves the logging invocations into the core modules when they are needed. AspectJ-based logging reverses the dependency between the core modules and the logger; it is the aspect that encodes how the operations in the core modules are logged instead
of each core module deciding for itself.
posted @ 2005-08-29 10:52 Dave 阅读(788) | 评论 (2)编辑 收藏
 

泛型的引入使得 Java 语言中的类型系统更加复杂。以前,该语言具有两种类型 —— 引用类型和基本类型。对于引用类型,类型 的概念基本上可以互换,术语子类型子类 也可以互换。

随着泛型的引入,类型和类之间的关系变得更加复杂。List<Integer>List<Object> 是不同的类型,但是却是相同的类。尽管 Integer 扩展 Object,但是 List<Integer> 不是 List<Object>,并且不能赋给 List<Object> 或者强制转换成 List<Object>

另一方面,现在有了一个新的古怪的类型叫做 List<?>,它是 List<Integer>List<Object> 的父类。并且有一个更加古怪的 List<? extends Number>。类型层次的结构和形状也变得复杂得多。类型和类不再几乎是相同的东西了。

extends 的新含意 

在 Java 语言引入泛型之前,extends 关键字总是意味着创建一个新的继承自另一个类或接口的类或接口。

引入泛型之后,extends 关键字有了另一个含意。将 extends 用在类型参数的定义中(Collection<T extends Number>)或者通配符类型参数中(Collection<? extends Number>)。

当使用 extends 来指示类型参数限制时,不需要子类-父类关系,只需要子类型-父类型关系。还要记住,有限制类型不需要是该限制的严格子类型;也可以 该限制。换句话说,对于 Collection<? extends Number>,您可以赋给它 Collection<Number>(尽管 Number 不是 Number 的严格子类型)和 Collection<Integer>Collection<Long>Collection<Float> 等等。

在任何这些含意中,extends 右边的类型都可以是参数化类型(Set<V> extends Collection<V>)。

posted @ 2005-08-24 11:36 Dave 阅读(186) | 评论 (0)编辑 收藏
Eclipse 运行命令行参数大全  
  包括英文版本和中文版本两种的说明, 特别需要值得一提的是那个 -nl 参数, 可以指定程序启动时所使用的语言. 例如:
eclipse -nl en_US
将启动英文语言, 这个特性在安装了国际化语言包以后特别有用, 可以方便的切换各个语言的版本. 注意 IBM WSAD v5.1 也支持这个功能. 

运行 Eclipse
将 Eclipse 驱动程序安装(解压缩)到某个目录(例如,c:\eclipse)中之后,通过运行顶级安装目录中的 Eclipse 可执行文件来启动"工作台"。在 Windows 系统上,该可执行文件称为 eclipse.exe,而在 Linux 系统上称为 eclipse。注意:下列讨论描述 Windows 系统上的设置。Linux 上的设置是相似的。

如果您没有另行指定,则平台将缺省工作区目录创建为可执行文件的兄弟目录(例如 c:\eclipse\workspace)。此工作区目录用作项目的缺省内容区,还用于保存任何必需的元数据。要进行共享安装或多工作区安装,应明确指出工作区的位置而不是使用缺省值。有两种控制工作区位置的方法:使用当前工作目录或使用 -data 命令行自变量。

将工作区位置设置为在当前工作目录内
在此方案中,工作区位置将是当前工作目录中称为 workspace 的目录。

实现此目的最容易的方法可能是使用下列步骤来创建快捷方式:

导航到 Windows 资源管理器中的 eclipse.exe 并使用右键拖动来创建 eclipse.exe 的快捷方式。 
编辑快捷方式的属性,以使启动位置:字段标识工作区位置的父目录(例如,c:\users\robert)。 
关闭属性对话框并双击快捷方式(如果提供的目录为 c:\users\robert,则工作区位置将为 c:\users\robert\workspace)。 
当然,您也可以使用命令提示符(通过将目录切换为工作区父目录然后运行 eclipse.exe)来获得同样的效果。

使用 -data 设置工作区的特定位置
要使用 -data 命令行自变量,只要将 -data your_workspace_location(例如,-data c:\users\robert\myworkspace)添加至快捷方式属性中的目标字段或显式地将它包括在命令行上。

使用 -vm 设置 java VM
建议显式指定在运行 Eclipse 时要使用哪个 Java VM。使用 -vm 命令行自变量(例如,-vm c:\jre\bin\javaw.exe)可以实现此目的。如果不使用 -vm,则 Eclipse 将使用在 O/S 路径上找到的一个 Java VM。当安装其它产品时,它们可更改您的路径,导致在下一次启动 Eclipse 时使用另一 Java VM。

运行 Eclipse 中的高级主题
Eclipse 可执行文件及平台本身提供了人们感兴趣的开发或调试 Eclipse 各部件的许多执行选项。运行 Eclipse 可执行文件的一般格式是:

eclipse [platform options] [-vmargs [Java VM arguments]]
Eclipse 启动参数  命令 描述  原因 
-arch architecture
 定义 Eclipse 平台在其上运行的处理器体系结构。Eclipse 平台通常使用 Java os.arch 属性的常用值来计算最佳设置。如果在此处指定该项,则这是 Eclipse 平台使用的值。此处指定的值可作为 BootLoader.getOSArch() 用于插件。示例值有:"x86"、"sparc"、"PA-RISC"和"ppc"。 2.0 
-application applicationId
 要运行的应用程序。应用程序由向 org.eclipse.core.runtime.applications 扩展点提供扩展的插件来声明。通常不需要此自变量。如果指定了此项,则该值会覆盖配置提供的值。如果不指定此项,则会运行"Eclipse 工作台"。 1.0 
-boot bootJarURL
 (建议不使用;用 -configuration 代替;支持 1.0 兼容)。Eclipse 平台的引导插件代码(boot.jar)的位置,表示为 URL。如果指定此项,则会用它来为装入 Eclipse 平台引导程序类装入器的类装入器设置类路径。仅当更改 startup.jar 和 boot.jar 的相对位置时才需要它。注意,不允许使用相对 URL。  *1.0 
-classloaderproperties [file]
 如果指定的话,则使用给定位置处的类装入器属性文件来激活平台类类装入器增强。文件自变量可以是文件路径或 URL。注意,不允许使用相对 URL。单击此处以获得更多详细信息。 2.0.2 
-configuration configurationFileURL
 Eclipse 平台配置文件的位置,表示为 URL。配置文件确定 Eclipse 平台、可用插件集和主要功能部件的位置。注意,不允许使用相对 URL。当安装或更新 Eclipse 平台时配置文件被写至此位置。  2.0 
-consolelog
 将 Eclipse 平台的错误日志镜像到用来运行 Eclipse 的控制台。与 -debug 组合时很方便使用。 1.0 
-data workspacePath
 要运行 Eclipse 平台的工作区的路径。工作区位置也是项目的缺省位置。相对于从中启动 eclipse 的目录来解释相对路径。 1.0 
-debug [optionsFile]
 将平台置于调试方式,并从给定位置处的文件装入调试选项(如果指定的话)。此文件指示哪些调试点可用于插件以及是否已启用它们。如果未给出文件位置,则平台在启动 eclipse 的目录中查找称为".options"的文件。URL 和文件系统路径都可作为文件位置。 1.0 
-dev [classpathEntries]
 将平台置于开发方式。将可选类路径条目(用逗号分隔的列表)添加至每个插件的运行时类路径。例如,当工作区包含要开发的插件时,指定 -dev bin 会为每个插件项目的名为 bin 的目录添加类路径条目,允许在其中存储最新生成的类文件。除去了冗余或不存在的类路径条目。 1.0 
-endsplash params
 用于在 Eclipse 平台启动并运行时关闭闪屏的内部选项。此选项在闪屏处理链中不同的位置有不同的语法和语义。 2.0 
-feature featureId
 主要功能部件的标识。主要功能部件为 Eclipse 的已启动实例提供了产品个性,并确定使用的产品定制信息。 2.0 
-keyring keyringFilePath
 磁盘上授权数据库(或"密钥环"文件)的位置。此自变量必须与 -password 选项配合使用。相对于从中启动 eclipse 的目录来解释相对路径。 1.0 
-nl locale
 定义 Eclipse 平台在其上运行的语言环境的名称。Eclipse 平台通常自动计算最佳设置。如果在此处指定该项,则这是 Eclipse 平台使用的值。此处指定的值可作为 BootLoader.getNL() 用于插件。示例值有:"en_US"和"fr_FR_EURO"。 2.0 
-nolazyregistrycacheloading
 取消激活装入优化的平台插件注册表高速缓存。缺省情况下,仅当需要时才从注册表高速缓存(可用时)中装入扩展的配置元素,以减少内存占用。此选项将在启动时强制完全装入注册表高速缓存。 2.1 
-noregistrycache
 绕过读写内部插件注册表高速缓存文件。 2.0 
-nosplash
 运行平台而不显示闪屏。 1.0 
-os operatingSystem
 定义 Eclipse 平台在其上运行的操作系统。Eclipse 平台通常使用 Java os.name 属性的常用值来计算最佳设置。如果在此处指定该项,则这是 Eclipse 平台使用的值。此处指定的值可作为 BootLoader.getOS() 用于插件,并用于解析插件清单文件中提及的路径中 $os$ 变量的出现。示例值有:"win32"、"linux"、"hpux"、"solaris"和"aix"。 1.0 
-password password
 授权数据库的密码。与 -keyring 选项配合使用。 1.0 
-perspective perspectiveId
 启动时要在活动工作台窗口中打开的透视图。如果没有指定该参数,则将打开关闭时活动的透视图。 1.0 
-plugincustomization   propertiesFile
 包含插件首选项缺省设置的属性文件的位置。这些缺省设置覆盖在主要功能部件中指定的缺省设置。相对于从中启动 eclipse 的目录来解释相对路径。 2.0 
-plugins pluginsFileURL
 (建议不使用;用 -configuration 代替;支持 1.0 兼容)。 指定 Eclipse 平台查找插件的文件的位置,表示为 URL。该文件为属性文件格式,其中键是任意用户定义名称,值是指向 plugin.xml 文件的显式路径或指向包含插件的目录的路径的用逗号分隔的列表。注意,不允许使用相对 URL。如果指定此项,则此选项会导致创建适当的临时配置。 *1.0 
-refresh 
 启动时执行工作区的全局刷新的选项。这将使从上次平台运行以来在文件系统中所做的任何更改一致。 1.0 
-showlocation 
 用于在窗口标题栏中显示工作区的位置的选项。在发行版 2.0 中,此选项仅与 -data 命令行自变量一起使用。 2.0 
-showsplash params
 用于显示闪屏(由可执行的 Eclipse 平台启动器执行)的内部选项。此选项在闪屏处理链中不同的位置有不同的语法和语义。 2.0 
-vm vmPath
 要用来运行 Eclipse 平台的"Java 运行时环境"(JRE)的位置。如果不指定此项,则 JRE 位于 jre(它是 Eclipse 可执行文件的兄弟目录)。相对于从中启动 eclipse 的目录来解释相对路径。 1.0 
-ws windowSystem
 定义 Eclipse 平台在其上运行的 Windows 系统。Eclipse 平台通常使用 Java os.name 属性的常用值来计算最佳设置。如果在此处指定该项,则这是 Eclipse 平台使用的值。此处指定的值可作为 BootLoader.getWS() 用于插件、用于配置 SWT 以及用于解析插件清单文件中提及的路径中 $ws$ 变量的出现。示例值有:"win32"、"motif"和"gtk"。 1.0 

将 -vmargs 条目后面的所有自变量(但不包括 -vmargs)作为虚拟机自变量(即,在要运行的类的前面)直接传递到所指示的 Java VM。注意:如果 Eclipse 启动在 Java vm 自变量(-vmargs)之后提供的自变量(例如,-data),则 Eclipse 将不会启动并且您将接收到"JVM 已终止。出口代码为 1"的错误。

在不同的 VM 上运行 
在 J9 上运行 Eclipse
当在 J9 版本 1.5 上运行 Eclipse 时,建议使用以下 VM 选项: 

eclipse.exe [eclipse arguments] -vm path_to_j9w.exe             -vmargs -ms:32 -mm:2048 -mo:32768 -moi:32768 -mca:32 -mco:128 -mx:2000000
当在 J9 版本 2.0 上运行 Eclipse 时,J9W 选择的缺省自变量应为合适的选项。但是,要覆盖 Eclipse 可执行文件以内部方式自动设置的参数,必须指定 -vmargs 不带任何参数,如下所示: 

eclipse.exe [eclipse arguments] -vm path_to_j9w.exe -vmargs
有关进一步信息,参考 J9 VM 文档和帮助。

在 IBM Developer Kit, Java(TM) Technology Edition VM 上运行 Eclipse
IBM Developer Kit, Java(TM) Technology Edition 1.3 Linux 的缺省 VM 设置适合进行初期研究工作,但在进行大型开发时是不够的。对于大型开发,应修改 VM 自变量以使有更多的堆可用。例如,下列设置将允许 Java 堆增大为 256MB:
posted @ 2005-08-22 10:49 Dave 阅读(209) | 评论 (0)编辑 收藏
爱因斯坦曾经说:“任何事情都应该越简单越好,而不是比较简单。”实际上,科学真理的目的就是在假设的前提下去简化一个理论,这样,人们可以去关注真正重要的问题。在企业软件开发中,道理是一样的。
  简化企业软件开发的一个关键是,提供一个这样的应用框架:它可以使开发人员不用关注于很多复杂的问题,比如事务处理、安全和持久化等。一个设计良好的框架将提升代码的可复用性,提高开发者的效率,并得到更高质量的软件。然而,目前J2EE 1.4下的EJB 2.1 框架被广泛认为是设计较差而且过度复杂的。不满足于EJB2.1框架,JAVA开发者使用了很多其他的中间件服务产品。最值得关注的是,以下两个框架吸引了大量开发者的兴趣和积极反馈。这两个框架很可能成为未来企业JAVA应用开发框架的选择。
  Spring框架是一个广受欢迎的但是非标准的开源框架。它主要由Interface21公司开发和控制。Spring框架的体系结构是基于注射依赖(DI)模式。Spring框架使用了大量的XML配置文件,它可以独立应用,或者在现有的应用服务器上工作。
  EJB 3.0框架是JCP定义的并且被所有主流J2EE提供商支持的标准框架。EJB 3.0规范的预发布版本目前已经有开源的和商业的实现,如JBOSS和ORACLE。EJB 3.0大量使用了JAVA注解(Java annotations,是JDK1.5提供的新功能。译者注)
  这两个框架有着一个共同的核心设计理念:它们的目标是为松耦合的POJO类提供中间件服务。框架通过在运行时截取执行环境,或将服务对象注射给POJO类的方式,将应用服务和POJO类“连接”起来。POJO类本身并不关注如何“连接”,而且也很少依赖于框架。这样,开发者可以将注意力集中在业务逻辑上,可以对他们的POJO类进行与框架无关的单元测试。并且,由于POJO类不需要继承框架的类或实现框架提供的接口,开发者可以在更加灵活性的基础上构建继承体系,和搭建应用。
  尽管有着共同的理念,但这两个框架采取了不同的方式来提供POJO服务。由于已经出版了大量的比较Spring与EJB2.1或者EJB3.0与EJB2.1的书籍和文章,而没有关于比较Spring和EJB3.0的认真研究,因此,本文将考察它们之间几个关键的不同,讨论他们优缺点。本文谈到的主题同样适用于其他不太有名的但同样提供“松耦合POJO” 设计的企业中间件框架。我希望,这篇文章可以帮助你选者最合适的你需求的框架。
提供商无关性
  开发者选择JAVA平台的一个最重要的原因就是它的提供厂商无关性。EJB 3.0是一个被设计为对提供商没有依赖性的开放的标准。EJB 3.0规范由企业JAVA社区的主流开源组织和厂商共同编写和支持的。EJB 3.0框架使开发者的应用程序实现可以独立于应用服务器。比如,JBoss的EJB 3.0的实现是基于Hibernate的,Oracle的EJB 3.0实现是基于TopLink的,但是,在JBoss或者Oracle上跑应用程序,开发者既不需要去学习Hibernate,也不需要学习TopLink提供的独特API。厂商无关性使EJB 3.0框架区别于当前其他任何的POJO中间件框架。
  然而,就象很多EJB 3.0的批评者很快指出的一样,目前EJB 3.0规范正在编写还未完全完成最终发布版。很有可能,还需要1至2年,EJB 3.0才会被主流J2EE厂商完全接受。但是,就算你的应用服务器本身不支持EJB 3.0,你也可以通过下载和安装一个“可嵌入的” EJB 3.0产品,来使你的应用服务器支持EJB 3.0应用。比如,JBoss“可嵌入的” EJB 3.0产品是开源的,它可以运行在任何兼容J2SE-5.0环境下(如你的应用服务器),目前处于Beta版测试中。其他厂商同样可以快速发布他们自己的可嵌入EJB 3.0产品,特别是规范中“数据持久化”部分。
  另一方面,Spring一直是一个非标准的技术,而且在可以预计的未来仍将如此。尽管你在任何应用服务器都上可以使用Spring框架,但基于Spring的应用仍然被限制于Spring本身和在你的应用中使用到的Spring提供的各种特别服务。
  由于Spring框架是一个开源项目,因此,它使用的配置文件XML格式和开发接口都是私有的。当然,这种限制不仅体现在Spring框架中,其他任何非标准产品都会有这种限制。但是,你的Spring应用的长期生存能力将依赖于Spring项目本身(或者说Interface 21公司,因为它雇佣了大多数的Spring核心开发人员)。并且,如果你使用了Spring提供的特殊服务,如Spring事务管理器或者Spring MVC,你同样被限制于Spring提供的API。
  并且,Spring应用是知道后端服务提供者的(即应用程序是知道服务提供者的,这样应用程序将会在一定程度上依赖于服务提供方:译者注)。例如,对于数据持久化服务,Spring框架提供了不同的DAO和模板Helper类,用于JDBC、Hibernate,、iBatis和JDO。这样,假如你需要改变一个Spring应用的持久化服务提供者(如,从JDBC换到Hibernate),你将需要重构你的系统应用代码,来使用新的Helper类。
服务整合
  Spring框架是建立在应用服务器和服务库之上,它的服务整合代码(如数据访问模板和Helper类)是基于框架的,并暴露给应用开发者。相反,EJB 3.0框架是紧密整合到应用服务器中的,它的服务整合代码是封装在一个标准的接口下的。
  因此,EJB 3.0厂商可以轻松的优化整体性能和开发者体验。如,在JBoss的EJB 3.0实现中,当你通过实体管理器持久化一个实体BEAN POJO时,Hibernate session事务将在JTA事务提交时自动提交。通过使用简单的@PersistenceContext注解(例子参看后面文章),你可以甚至可以将实体管理器和其下的Hibernate事务绑定到一个有状态的session bean上。应用程序事务可以在一个session中跨越多个线程,在事务性的WEB应用中这是非常有用的,如多页面的购物车。
  基于EJB 3.0 框架、Hibernate、和JBoss 内部Tomcat的紧密整合,上面提到的简单的整合的编程接口是可能的。Oracle的EJB 3.0框架和它内部的Toplink持久服务可以达到同样层次的整合。
  EJB 3.0中整合服务的另一个好例子是集群支持。假如你部署一个EJB 3.0应用到一个集群服务器,所有的故障切换、负载均衡、分布式缓存、和状态复制服务对于应用程序来说,都是自动完成的。集群服务被隐藏在EJB 3.0编程接口之下,对于EJB 3.0开发者来说,这些服务都是完全透明的。
  在Spring中,优化框架和服务之间交互更加困难一些。例如,想要用Spring的声明式事务服务来管理Hibernate事务,必须在XML配置文件中明确的配置Spring的事务管理器(TransactionManager)和Hibernate SessionFactory对象。Spring应用开发者必须自己管理跨越多个HTTP请求的事务。并且,没有简单的方法可以在Spring应用中实现集群服务
服务聚合的灵活性
  由于Spring中的服务整合代码是作为编程接口暴露给应用开发者的,因此开发人员可以根据需要来聚合多个服务。这个特性使你可以集成一个你自己的“轻量”级应用服务器。Spring的一个通常的用法是将Tomcat和Hibernate连接起来来支持简单的数据库驱动的WEB应用程序。在这种情况下,Spring本身提供了事务管理服务,Hibernate提供了持久化服务,这种设置本身就创建了一个小型的应用服务器。
  通常,EJB 3.0应用服务器不提供给开发者这种按照你的需要来选择服务的灵活性。大多数情况,你会得到一系列已经预先打包好的特性,其中有些你可能是不需要的。然而,如果应用服务器提供了模块内部的独特设计,就象JBOSS一样,你可以不去关心这些不必要的特性。在任何情况下,去定制一个全功能的应用服务器并不是一个琐碎而没有意义的工作。
  当然,如果一个应用不是一个单一的结点,你将需要连接多个应用服务器提供的服务(如资源池、消息队列和集群)。这种情况下,从总的资源消耗上看,Spring框架就和任何EJB 3.0方案一样是“重量级”的。
  为了进行容器外的单元测试,Spring的灵活的服务聚合也可以来连接假对象,来替代真的服务对象。在EJB 3.0应用中,大多数的组件都是简单POJO,他们可以容易进行容器外的单元测试。但是,如果要测试与容器服务相关的服务对象(如持久化实体管理器),更好的方式是进行容器内的测试,因为这样比使用假对象来替代的方式更加容易,更加健壮,而且更加准确。
XML vs. 注解
  从应用开发者的角度来看,Spring的编程接口主要基于XML配置文件,而EJB 3.0则大量的使用了JAVA注解。XML文件可以表达复杂的关系,但是它们更加冗长而且不健壮。注解的方式很简单明了,但是很难去表达复杂的或者继承性的结构。
  Spring和EJB 3.0分别选择了XML和注解方式,这取决于框架的体系结构:由于注释只能描述相当少的配置信息,只有一个预先整合好的框架(如大多数重要事情已经在框架中实现了)才能大量的使用注释作为它的配置选项。象我们讨论的一样,EJB 3.0满足了这些要求,而Spring作为一个一般的注射依赖框架,它没有做到这一点。
  当然,由于EJB 3.0和Spring相互学习了很多特性,所以,它们都在某种层次上支持XML和注释。例如,EJB 3.0中可以应用XML配置文件来作为一个选择性的机制,用来改变注释的默认行为。注释也可以用来配置一些Spring服务。
  研究XML和注释直接区别的最好的方式就是通过例子。在下面的几节中,我们将一起看一下EJB 3.0和Spring是如何为应用程序提供关键服务的。
声明式服务
  EJB 3.0和Spring都将运行时服务(如事务管理、安全、日志、消息、和信息服务)连接给应用程序。由于这些服务同应用程序的业务逻辑并不是直接相关的,因此,它们不被应用程序本身来管理。相反,这些服务被服务容器(如EJB 3.0和Spring)以不可见的方式在运行时提供给应用程序。开发人员(或系统管理员)通过配置来告诉容器什么时候,以怎样的方式来应用这些服务。
  EJB 3.0通过JAVA注解的方式来配置声明式服务,Spring则通过XML配置文件来完成。大多数情况下,EJB 3.0 的注解方式是应用这种服务的更加简单和优美的方式。下面是一个在EJB 3.0中对一个POJO的方法使用事务管理服务的例子。
  public class Foo {
      @TransactionAttribute(TransactionAttributeType.REQUIRED)
      public bar () {
        // do something ...
      }   
  }
  你可以对一段代码声明多个属性,并应用多个服务。下面是一个对EJB 3.0中POJO类同时使用事务管理服务和安全服务的例子。
  @SecurityDomain("other")
  public class Foo {
      @RolesAllowed({"managers"})
      @TransactionAttribute(TransactionAttributeType.REQUIRED)
      public bar () {
        // do something ...
      }  
  }
  使用XML指定代码属性和配置声明服务将导致冗长的和不桅顶的配置文件。下面是Spring应用中一个XML元素的例子,它用来在Foo.bar()方法上应用一个非常简单的Hibernate事务。
<!-- Setup the transaction interceptor -->
<bean id="foo"
  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="target">
        <bean class="Foo"/>
    </property>
    <property name="transactionManager">
        <ref bean="transactionManager"/>
    </property>
    <property name="transactionAttributeSource">
        <ref bean="attributeSource"/>
    </property>
</bean>
<!-- Setup the transaction manager for Hibernate -->
<bean id="transactionManager"
  class="org.springframework.orm.hibernate.HibernateTransactionManager">
    <property name="sessionFactory">
        <!-- you need to setup the sessionFactory bean in yet another XML element -->
        <ref bean="sessionFactory"/>
    </property>
</bean>
<!-- Specify which methods to apply transaction -->
<bean id="transactionAttributeSource"
class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
    <property name="properties">
        <props>
            <prop key="bar">
        </props>
    </property>
</bean>
  XML文件的复杂程度将随着你对同一个POJO类增加的拦截器的数量程几何增长。意识到了仅使用XML配置文件的限制性,Spring支持在JAVA源代码中使用Apache Commons metadata来指定事物属性。在最新的Spring 1.2中,JDK-1.5风格的注释也被支持。为了使用事务元数据,你需要为上面例子中的AttributesTransactionAttributeSource 改变一个transactionAttributeSource bean,并且增加一个附加的对元数据拦截器的设置。
<bean id="autoproxy"
 class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean id="transactionAttributeSource"
  class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource"
    autowire="constructor"/>
<bean id="transactionInterceptor"
    class="org.springframework.transaction.interceptor.TransactionInterceptor"
    autowire="byType"/>
<bean id="transactionAdvisor"
    class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"
    autowire="constructor"/>
<bean id="attributes"
class="org.springframework.metadata.commons.CommonsAttributes"/>
  
  当你有许多事务方法时,Spring元数据简化了transactionAttributeSource元素。但是它没有解决XML配置文件的根本问题:仍然需要冗长的、易错的事务拦截器,事务管理器,和事务属性。
注射依赖
  中间件容器的一个主要优点是它们使得程序开发人员可以去构建松耦合的应用程序。服务使用者仅仅需要知道服务接口就可以使用服务。容器把具体的服务实现实例化,然后将它们提供给服务使用者。这样,容器可以在可替换的服务实现之间进行切换,而不改变服务接口和服务使用者代码。
  注射依赖模式是实现松耦合应用程序的一个最好的方式。比起以前的方式,如通过JNDI进行查找或回调容器,注射依赖模式更容易使用,而且更加优美。使用注射依赖模式,框架扮演了构建服务的对象工厂角色,然后根据运行时的配置,把这些服务对象注射到应用程序的POJO类中。从程序开发人员的角度看,作为客户端使用者的POJO在需要使用服务对象前就自动的得到了它们。
  Spring 和 EJB 3.0都提供了大量的DI模式支持。但是,它们之间也有着根本的不同。Spring支持了通常意义上的但是复杂的基于XML配置文件的注射依赖API;EJB 3.0支持的注射大多数通用服务对象(如,EJB和容器对象)和JNDI对象,它通过简单的JAVA注解来完成。
  EJB 3.0的注射注解相当的简洁易用。@Resource标签注射大多数的通过服务对象和JNDI对象。下面的例子显示了如何将JNDI提供的服务器缺剩数据源对象注射给一个POJO的一个字段。DefaultDS是这个数据源的JNDI名字。myDb 变量在第一次被使用前就自动被赋予了正确的值。
  public class FooDao {
      @Resource (name="DefaultDS")
      DataSource myDb;
      // Use myDb to get JDBC connection to the database
  }
  在EJB 3.0中,注释@Resource不仅可以直接注射给属性变量,它也可以通过setter方法来完成注射。下面的例子将一个session上下文对象通过setter方法注射给使用者。应用程序不用显示的调用setter方法,在任何其他方法被调用前容器将调用setter方法完成注射。
  @Resource
  public void setSessionContext (SessionContext ctx) {
      sessionCtx = ctx;
  }
  对于更复杂的服务对象,还有一些特殊的注射注解。例如,@EJB 注解被用来注射EJB stubs,@PersistenceContext注解被用来注射实体管理器对象,这些对象负责处理EJB 3.0实体Bean的数据访问操作。 下面的例子给出如何将一个实体管理器注射到一个有状态Session Bean中。@PersistenceContext注解的类型属性描述了被注射的的实体管理器有一个扩展的事务容器:它不会随着JTA事务管理器自动提交事务,因此它可以应用在当session中有多次操作的应用事务管理时。
  @Stateful
  public class FooBean implements Foo, Serializable {
      @PersistenceContext(
        type=PersistenceContextType.EXTENDED
      )
      protected EntityManager em;
      public Foo getFoo (Integer id) {
          return (Foo) em.find(Foo.class, id);
      }
  }

  EJB 3.0 规范定义了可以通过注解来被注射使用的服务器资源。但是,它不支持用户自定义的POJO类之间的相互注射。
  在Spring中,为了将服务对象注射到你的POJO类中,你首先需要定义一个setter方法(或有参数的构造函数) 。下面的例子演示了 POJO 类中一个Hibernate session 工厂的属性。
  public class FooDao {
      HibernateTemplate hibernateTemplate;
      public void setHibernateTemplate (HibernateTemplate ht) {
          hibernateTemplate = ht;
      }
      // Use hibernateTemplate to access data via Hibernate
      public Foo getFoo (Integer id) {
          return (Foo) hibernateTemplate.load (Foo.class, id);
      }
  }
  因此,你可以指定容器如何得到这个服务,并且在运行时通过配置文件中XML元素的连接关系把它提供给POJO。下面的例子显示了连接一个数据源到一个Hibernate session 工厂、session 工厂到Hibernate模板对象、模板对象最后到应用程序POJO类,整个过程的XML配置。
  Spring 代码复杂性的部分原因是,我们需要手工的去注射Hibernate相关类,然而,EJB 3.0 实体管理器被服务器自动管理和配置。但是,这使我们返回到了这样的讨论:Spring 不象EJB 3.0 一样,它不同服务紧密整合在一起。
<bean id="dataSource"
  class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiname">
        <value>java:comp/env/jdbc/MyDataSource</value>
    </property>
</bean>
<bean id="sessionFactory"
  class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
    <property name="dataSource">
        <ref bean="dataSource"/>
    </property>
</bean>
<bean id="hibernateTemplate"
  class="org.springframework.orm.hibernate.HibernateTemplate">
    <property name="sessionFactory">
        <ref bean="sessionFactory"/>
    </property>   
</bean>
<bean id="fooDao" class="FooDao">
    <property name="hibernateTemplate">
        <ref bean="hibernateTemplate"/>
    </property>
</bean>
<!-- The hibernateTemplate can be injected into more DAO objects -->
  尽管Spring中基于XML的注射依赖比较复杂,但是它非常强大。你可以注射任何POJO到另外的POJO中,包括程序中自定义的。
  如果你确实想在EJB 3.0应用中使用Spring的注射依赖功能,你可以将一个Spring Bean工厂类通过JNDI注射到一个EJB中。在某些EJB 3.0 应用服务器中,厂商可能会定义一些非标准的API用来注射任意的POJO类。一个很好的例子是JBoss MicroContainer,它处理了AOP依赖性,因此它是甚至比Spring 更加通用。
  
结论
  尽管Spring 和EJB 3.0的目标都是提供企业服务,使得POJO可以松耦合,但是它们实现的方式非常不同。在两个框架中注射依赖模式都有大量的应用。
  通过EJB 3.0的标准方式、大量应用的注解、还有同应用服务器紧密整合性,这些提供了更高的厂商无关性和开发人员工作效率。Spring的以XML为中心的配置文件和注射依赖的连贯使用,允许开发人员去构造更加灵活的应用系统,并且可以同时与多个应用服务提供者同时工作。
  
感谢
 
 作者感谢Stephen Chambers, Bill Burke, 和Andy Oliver 的有价值的评论.
参考
  The Spring framework (参考CodeZoo: Spring)
EJB 3.0
JBoss EJB 3.0
Oracle Application Server EJB 3.0 Preview
Michael Juntao Yuan specializes in end-to-end enterprise solutions and is a mobile geek and avid open source supporter.


posted @ 2005-08-22 10:13 Dave 阅读(226) | 评论 (0)编辑 收藏
􀂄 bsh-deployer:将BeanShell脚本部署成JBoss服务。
􀂄 cache-invalidation-service.xml:允许借助于JMS,而实现对EJB缓存的控制。
􀂄 client-deployer-service.xml:部署J2EE应用客户。
􀂄 ear-deployer.xml:部署J2EE EAR应用。
􀂄 ejb-deployer.xml:部署J2EE EJB应用。
􀂄 hsqldb-ds.xml:设置嵌入式Hypersonic数据库服务,并将其作为默认数据源。
􀂄 http-invoker.sar:通过RMI/HTTP方式访问到MBean和EJB。
􀂄 jboss-aop.deployer:提供AspectManagerService,并部署JBoss AOP应用。
􀂄 jboss-hibernate.deployer:部署Hibernate存档(HAR文件)。
􀂄 jboss-local-jdbc.rar和jboss-xa-jdbc.rar:集成JDBC驱动的JCA资源适配器,它们分别支持DataSource和XADataSource。但是,这并没有提供专有JCA实现。
􀂄 jboss-ws4ee.sar:提供J2EE Web服务支持。
􀂄 jbossjca-service.xml:JBoss JCA实现,使得在JBoss中部署JCA资源适配器成为可能。
􀂄 jbossweb-tomcat50-sar:含有嵌入式Tomcat服务的展开SAR文件。它为JBoss提供了标准的Web容器。
􀂄 jms:将JMS相关的服务聚集在一起,并放置在jms目录中。
􀂄 hsqldb-jdbc-state-service.xml:使用HSQLDB管理状态。
􀂄 hsqldb-jdbc2-service.xml:使用嵌入式HSQL数据库实现缓存和持久化。它还包含了JMS实现的核心服务,即DestinationManager MBean。
􀂄 jbossmq-destinations-service.xml:供JBoss测试套件使用的JMS Topic和Queue。
􀂄 jbossmq-service.xml:JMS其他服务,包括拦截器配置。
􀂄 jms-ds.xml:将JBoss消息实现作为默认JMS提供商。并且,它还提供JCA配置信息,以供集成JBoss JCA和JMS资源适配器使用。
􀂄 jms-ra.rar:资源适配器,供JCA处理JMS连接工厂使用。
􀂄 jbossmq-httpil.sar:提供JMS调用层,从而实现HTTP方式使用JMS。
􀂄 jvm-il-service.xml:配置本地JMS传输调用层,供本地JVM使用JMS。
􀂄 uil2-service.xml:配置JMS版本2统一调用层。这是一种可靠的、自定义的、基于Socket的传输方式。推荐在不同JVM间使用它。
􀂄 jmx-console.war:JMX控制台应用。前面讨论过。
􀂄 jmx-invoker-server.xml:为远程访问JMX MBean服务器提供支持。
􀂄 mail-ra.rar:为JavaMail提供资源适配器。
􀂄 mail-service.xml:允许应用和服务在JBoss中使用JavaMail。请注意,邮件服务器相关信息必须由用户提供。
􀂄 management:含有可更换管理服务的子目录。其中,包含有改进的Web控制台。
􀂄 monitoring-service.xml:配置警告监听器,比如控制台监听器、E_mail监听器,等等。
􀂄 properties-service.xml:设置JVM的全局系统属性(由System.getProperties返回)。
􀂄 schedule-manager-service.xml和scheduler-service.xml:定时任务服务。
􀂄 sqlexception-service.xml:为JDBC驱动提供标识一般性SQL异常。
􀂄 uuid-key-generator.sar:生成唯一的、基于UUID的键。
all配置提供了其他配置没有提供的其他服务,用户可以将这些服务集成到各自的服务器配置中。具体如下:
􀂄 cluster-service.xml:群集服务,包括JGroups集成服务、HA-JNDI、有状态会话Bean复制、CMP2缓存有效性服务。
􀂄 deploy-hasingleton-service.xml:HASingletonDeployer MBean。用于确保群集中只有单个节点在deploy-hasingleton目录部署了服务。
􀂄 deploy.last/farm-service.xml:farm群集部署服务。用于确保它在所有其他服务部署之后才部署其本身。
􀂄 ebxmlrr-service.xml:JAXR注册服务实现。
􀂄 iiop-service.xml:实现对CORBA、IIOP的支持。
􀂄 jbossha-httpsession.sar:遗留的HTTP会话复制服务。
􀂄 remoting-service.xml:还处于试验中的下一代分离式Invoker框架。
􀂄 snmp-adaptor.sar:将JMX通知转换成SNMP陷阱。
􀂄 tc5-cluster-service.xml:用于新的HTTP复制服务的TressCache配置。
posted @ 2005-08-22 09:25 Dave 阅读(1206) | 评论 (1)编辑 收藏