﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Jelver'Sky-文章分类-EJB/JBoss</title><link>http://www.blogjava.net/jelver/category/7670.html</link><description>“一直很多人说我是天才，但我却相信这个世界没有天才。如果没有卓越的努力和娴熟的球性，你永远不会踢出精彩的足球。我从3岁开始踢球，7岁进入格雷米奥少年队开始接受系统训练，至今为止已经踢了20年的球。如果你认为这纯粹是天才，那为什么我14岁时没有现在这种天才呢？我从来不会低估努力的重要性，而这正是我对自己的要求。”
---------罗纳尔迪尼奥(Ronaldinho)</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 21:58:29 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 21:58:29 GMT</pubDate><ttl>60</ttl><item><title>Java理论与实践:用动态代理进行修饰(转载)</title><link>http://www.blogjava.net/jelver/articles/80999.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Mon, 13 Nov 2006 15:17:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/80999.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/80999.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/80999.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/80999.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/80999.html</trackback:ping><description><![CDATA[
		<h1 class="xspace-title">Java理论与实践:用动态代理进行修饰(转载)</h1>
		<p class="xspace-smalltxt"> </p>
		<div class="xspace-itemmessage" id="xspace-showmessage">
				<font color="#333333">　动态代理为实现许多常见设计模式（包括 Facade、Bridge、Interceptor、Decorator、Proxy（包括远程和虚拟代理）和 Adapter 模式）提供了替代的动态机制。虽然这些模式不使用动态代理，只用普通的类就能够实现，但是在许多情况下，动态代理方式更方便、更紧凑，可以清除许多手写或生成的类。<br />　　<br />　　<b>Proxy 模式</b><br />　　<br />　　Proxy 模式中要创建“stub”或“surrogate”对象，它们的目的是接受请求并把请求转发到实际执行工作的其他对象。远程方法调用（RMI）利用 Proxy 模式，使得在其他 JVM 中执行的对象就像本地对象一样；企业 JavaBeans （EJB）利用 Proxy 模式添加远程调用、安全性和事务分界；而 JAX-RPC Web 服务则用 Proxy 模式让远程服务表现得像本地对象一样。在每一种情况中，潜在的远程对象的行为是由接口定义的，而接口本质上接受多种实现。调用者（在大多数情况下）不能区分出它们只是持有一个对 stub 而不是实际对象的引用，因为二者实现了相同的接口；stub 的工作是查找实际的对象、封送参数、把参数发送给实际对象、解除封送返回值、把返回值返回给调用者。代理可以用来提供远程控制（就像在 RMI、EJB 和 JAX-RPC 中那样），用安全性策略包装对象（EJB）、为昂贵的对象（EJB 实体 Bean）提供惰性装入，或者添加检测工具（例如日志记录）。<br />　　<br />　　在 5.0 以前的 JDK 中，RMI stub（以及它对等的 skeleton）是在编译时由 RMI 编译器（rmic）生成的类，RMI 编译器是 JDK 工具集的一部分。对于每个远程接口，都会生成一个 stub（代理）类，它代表远程对象，还生成一个 skeleton 对象，它在远程 JVM 中做与 stub 相反的工作 ―― 解除封送参数并调用实际的对象。类似地，用于 Web 服务的 JAX-RPC 工具也为远程 Web 服务生成代理类，从而使远程 Web 服务看起来就像本地对象一样。<br />　　<br />　　不管 stub 类是以源代码还是以字节码生成的，代码生成仍然会向编译过程添加一些额外步骤，而且因为命名相似的类的泛滥，会带来意义模糊的可能性。另一方面，动态代理机制支持在编译时没有生成 stub 类的情况下，在运行时创建代理对象。在 JDK 5.0 及以后版本中，RMI 工具使用动态代理代替了生成的 stub，结果 RMI 变得更容易使用。许多 <a onclick="javascript:tagshow(event, 'J2EE');" href="javascript:;" target="_self"><u><strong>J2EE</strong></u></a> 容器也使用动态代理来实现 EJB。EJB <a onclick="javascript:tagshow(event, '%BC%BC%CA%F5');" href="javascript:;" target="_self"><u><strong>技术</strong></u></a>严重地依靠使用拦截（interception）来实现安全性和事务分界；动态代理为接口上调用的所有方法提供了集中的控制流程路径。<br />　　<br />　　<b>动态代理机制</b><br />　　<br />　　动态代理机制的核心是 InvocationHandler 接口，如清单 1 所示。调用句柄的工作是代表动态代理实际执行所请求的方法调用。传递给调用句柄一个 Method 对象（从 <a onclick="javascript:tagshow(event, 'java');" href="javascript:;" target="_self"><u><strong>java</strong></u></a>.lang.reflect 包），参数列表则传递给方法；在最简单的情况下，可能仅仅是调用反射性的方法 Method.invoke() 并返回结果。<br />　　<br />　　清单 1. InvocationHandler 接口<br />　　<br />　　public interface InvocationHandler {<br />　　Object invoke(Object proxy, Method method, Object[] args)<br />　　throws Throwable;<br />　　}<br />　　<br />　　每个代理都有一个与之关联的调用句柄，只要代理的方法被调用时就会调用该句柄。根据通用的设计原则：接口定义类型、类定义实现，代理对象可以实现一个或多个接口，但是不能实现类。因为代理类没有可以访问的名称，它们不能有构造函数，所以它们必须由工厂创建。清单 2 显示了动态代理的最简单的可能实现，它实现 Set 接口并把所有 Set 方法（以及所有 Object 方法）分派给封装的 Set 实例。<br />　　<br />　　清单 2. 包装 Set 的简单的动态代理<br />　　<br />　　public class SetProxyFactory {<br />　　<br />　　public static Set getSetProxy(final Set s) {<br />　　return (Set) Proxy.newProxyInstance<br />　　(s.getClass().getClassLoader(),<br />　　new Class[] { Set.class },<br />　　new InvocationHandler() {<br />　　public Object invoke(Object proxy, Method method,<br />　　Object[] args) throws Throwable {<br />　　return method.invoke(s, args);<br />　　}<br />　　});<br />　　}<br />　　}<br />　　<br />　　SetProxyFactory 类包含一个静态工厂方法 getSetProxy()，它返回一个实现了 Set 的动态代理。代理对象实际实现 Set ―― 调用者无法区分（除非通过反射）返回的对象是动态代理。SetProxyFactory 返回的代理只做一件事，把方法分派给传递给工厂方法的 Set 实例。虽然反射代码通常比较难读，但是这里的内容很少，跟上控制流程并不难 ―― 只要某个方法在 Set 代理上被调用，它就被分派给调用句柄，调用句柄只是反射地调用底层包装的对象上的目标方法。当然，绝对什么都不做的代理可能有点傻，是不是呢？<br />　　<br />　　<b>什么都不做的适配器</b><br />　　<br />　　对于像 SetProxyFactory 这样什么都不做的包装器来说，实际有个很好的应用 ―― 可以用它安全地把对象引用的范围缩小到特定接口（或接口集）上，方式是，调用者不能提升引用的类型，使得可以更安全地把对象引用传递给不受信任的代码（例如插件或回调）。清单 3 包含一组类定义，实现了典型的回调场景。从中会看到动态代理可以更方便地替代通常用手工（或用 IDE 提供的代码生成向导）实现的 Adapter 模式。<br />　　<br />　　清单 3. 典型的回调场景<br />　　<br />　　public interface ServiceCallback {<br />　　public void doCallback();<br />　　}<br />　　<br />　　public interface Service {<br />　　public void serviceMethod(ServiceCallback callback);<br />　　}<br />　　<br />　　public class ServiceConsumer implements ServiceCallback {<br />　　private Service service;<br />　　<br />　　...<br />　　public void someMethod() {<br />　　...<br />　　service.serviceMethod(this);<br />　　}<br />　　}<br />　　<br />　　ServiceConsumer 类实现了 ServiceCallback（这通常是支持回调的一个方便途径）并把 this 引用传递给 serviceMethod() 作为回调引用。这种方法的问题是没有机制可以阻止 Service 实现把 ServiceCallback 提升为 ServiceConsumer，并调用 ServiceConsumer 不希望 Service 调用的方法。有时对这个风险并不关心 ―― 但有时却关心。如果关心，那么可以把回调对象作为内部类，或者编写一个什么都不做的适配器类（请参阅清单 4 中的 ServiceCallbackAdapter）并用 ServiceCallbackAdapter 包装 ServiceConsumer。ServiceCallbackAdapter 防止 Service 把 ServiceCallback 提升为 ServiceConsumer。<br />　　<br />　　清单 4. 用于安全地把对象限制在一个接口上以便不被恶意代码不能的适配器类<br />　　<br />　　public class ServiceCallbackAdapter implements ServiceCallback {<br />　　private final ServiceCallback cb;<br />　　<br />　　public ServiceCallbackAdapter(ServiceCallback cb) {<br />　　this.cb = cb;<br />　　}<br />　　<br />　　public void doCallback() {<br />　　cb.doCallback();<br />　　}<br />　　}<br />　　<br />　　编写 ServiceCallbackAdapter 这样的适配器类简单却乏味。必须为包装的接口中的每个方法编写重定向类。在 ServiceCallback 的示例中，只有一个需要实现的方法，但是某些接口，例如 Collections 或 JDBC 接口，则包含许多方法。现代的 IDE 提供了“Delegate Methods”向导，降低了编写适配器类的工作量，但是仍然必须为每个想要包装的接口编写一个适配器类，而且对于只包含生成的代码的类，也有一些让人不满意的地方。看起来应当有一种方式可以更紧凑地表示“什么也不做的限制适配器模式”。<br />　　<br />　　<b>通用适配器类</b><br />　　<br />　　清单 2 中的 SetProxyFactory 类当然比用于 Set 的等价的适配器类更紧凑，但是它仍然只适用于一个接口：Set。但是通过使用泛型，可以容易地创建通用的代理工厂，由它为任何接口做同样的工作，如清单 5 所示。它几乎与 SetProxyFactory 相同，但是可以适用于任何接口。现在再也不用编写限制适配器类了！如果想创建代理对象安全地把对象限制在接口 T，只要调用 getProxy(T.class,object) 就可以了，不需要一堆适配器类的额外累赘。<br />　　<br />　　清单 5. 通用的限制适配器工厂类<br />　　<br />　　public class GenericProxyFactory {<br />　　<br />　　public static&lt;T&gt; T getProxy(Class&lt;T&gt; intf,<br />　　final T obj) {<br />　　return (T)<br />　　Proxy.newProxyInstance(obj.getClass().getClassLoader(),<br />　　new Class[] { intf },<br />　　new InvocationHandler() {<br />　　public Object invoke(Object proxy, Method method,<br />　　Object[] args) throws Throwable {<br />　　return method.invoke(obj, args);<br />　　}<br />　　});<br />　　}<br />　　}<br />　　<br />　　<b>动态代理作为 Decorator</b><br />　　<br />　　当然，动态代理工具能做的，远不仅仅是把对象类型限制在特定接口上。从 清单 2 和 清单 5 中简单的限制适配器到 Decorator 模式，是一个小的飞跃，在 Decorator 模式中，代理用额外的功能（例如安全检测或日志记录）包装调用。清单 6 显示了一个日志 InvocationHandler，它在调用目标对象上的方法之外，还写入一条日志信息，显示被调用的方法、传递的参数，以及返回值。除了反射性的 invoke() 调用之外，这里的全部代码只是生成调试信息的一部分 ―― 还不是太多。代理工厂方法的代码几乎与 GenericProxyFactory 相同，区别在于它使用的是 LoggingInvocationHandler 而不是匿名的调用句柄。<br />　　<br />　　清单 6. 基于代理的 Decorator，为每个方法调用生成调试日志<br />　　<br />　　private static class LoggingInvocationHandler&lt;T&gt;<br />　　implements InvocationHandler {<br />　　final T underlying;<br />　　<br />　　public LoggingHandler(T underlying) {<br />　　this </font>
		</div>
<img src ="http://www.blogjava.net/jelver/aggbug/80999.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-11-13 23:17 <a href="http://www.blogjava.net/jelver/articles/80999.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3.0概览</title><link>http://www.blogjava.net/jelver/articles/77473.html</link><dc:creator>冰河快狼</dc:creator><author>冰河快狼</author><pubDate>Thu, 26 Oct 2006 13:00:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/77473.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/77473.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/77473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/77473.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/77473.html</trackback:ping><description><![CDATA[原文链接http://www.javaworld.com/javaworld/jw-08-2004/jw-0809-ejb.html<br /><br /><br /><br />译者语：<br /><br />翻译完这篇文章之后，感觉EJB3.0确实有了很大的改进，尤其在降低开发难度方面，个人认为EJB3.0采用注释的方式来简化开发确实是一个很好的注意。以前用过XDoclet或者BEA公司的WeblogicWorkShop（它的jws就是一个加了注释的java）的朋友对于这一技术应该不是很陌生。本文的作者是BEA公司的资深程序员他不仅向我们描述了最新的EJB3.0技术，而且提出了他个人的一些观点，非常值得我们参考，作者还在文末倡议大家一起参加到EJB3.0规范的制定中来。希望通过阅读本文能使你一窥EJB3.0的冰山一角。<br /><br />对于本文的中文翻译，作者保留其一切权利，如需转载需要经过译者的同意。谢谢Email:wafd@hotmail.com.<br /><br />引言<br /><br />期待以久的EJB3.0规范在最近发布了它的初稿。在本文中将对新的规范进行一个概要性的介绍，包括新增的元数据支持，EJBQL的修改，实体Bean模型访问bean上下文的新方法和运行时环境等等。作者还讨论了EJB在未来要作出的调整以及EJB3.0与其他开发规范之间的关系。<br /><br />开始<br /><br />无论如何由于EJB的复杂性使之在J2EE架构中的表现一直不是很好。EJB大概是J2EE架构中唯一一个没有兑现其能够简单开发并提高生产力的组建。EJB3.0规范正尝试在这方面作出努力以减轻其开发的复杂性。EJB3.0减轻了开发人员进行底层开发的工作量，它取消或最小化了很多（以前这些是必须实现）回调方法的实现，并且降低了实体Bean及O/R映射模型的复杂性。<br /><br />在本文中，我首先会介绍EJB3.0中几个主要的改变。它对进一步深入了解EJB3.0是非常重要的。随后，我会从更高的层面来描述已经被提交到EJB3.0规范中的细节，并一个个的讲解新的规范中的改变：实体Bean,O/R映射模型，实体关系模型和EJB QL(EJB查询语言)等等。<br /><br />背景<br /><br />EJB3.0中两个重要的变更分别是：使用了Java5中的程序注释工具和基于Hibernate的O/R映射模型。<br /><br />Java5中的元数据工具。<br /><br />Java5（以前叫J2SE1.5或Tiger）中加入了一种新的程序注释工具。通过这个工具你可以自定义注释标记，通过这些自定义标记来注释字段、方法、类等等。这些注释并不会影响程序的语义，但是可以通过工具（编译时或运行时）来解释这些标记并产生附加的内容（比如部署描述文件），或者强制某些必须的运行时行为（比如EJB组件的状态特性）。注释的解析可以通过源文件的解析（比如编译器或这IDE工具）或者使用Java5中的APIs反射机制。注释只能被定义在源代码层。由于所有被提交到EJB3.0草案中的注释标记都有一个运行时的RetentionPolicy，因此会增加类文件占用的存储空间，但这却给容器制造商和工具制造商带来了方便。<br /><br />Hibernate<br /><br />目前Hibernate非常受欢迎，它是开发源代码的Java O/R映射框架，目的是把开发人员从繁琐的数据持久化编程中解脱出来。它也有一个标准的HQL（Hibernate 查询语言）语言，你可以在新的EJB QL中看到它的影子。Hibernate在处理如数据查询、更新、连接池、事务处理、实体关系处理等方面非常简单。<br /><br />概览<br /><br />在已经提交的EJB3.0规范中主要涉及两个方面的改变：<br /><br />1.         一套以注释为基础的EJB编程模型，再加上EJB2.1中定义的通过部署描述符和几个接口定义的应用程序行为。<br /><br />2.         新的实体Bean持久化模型，EJBQL也有许多重要的改变。<br /><br />还有一些有关上述的提议，比如：一个新的客户端编程模型，业务接口的使用以及实体Bean的生命周期。请注意EJB2.1编程模型（包括部署描述符和home/remote接口）仍然是有效的。新的简化模型并没有完全取代EJB2.1模型。<br /><br />EJB注释<br /><br />EJB规范组织一个重要的目标是减轻原始代码的数量，并且他们为此给出了一个完美而简介的办法。在EJB3.0的里，任何类型的企业级Bean只是一个加了适当注释的简单Java对象(POJO)。注释可以用于定义bean的业务接口、O/R映射信息、资源引用信息，效果与在EJB2.1中定义部署描述符和接口是一样的。在EJB3.0中部署描述符不再是必须的了；home接口也没有了，你也不必实现业务接口（容器可以为你完成这些事情）。<br /><br />比如，你可以使用@Stateless注释标记类把Java类声明为一个无状态回话bean。对于有状态回话bean来说，@Remove注释可以用来标记一个特定的方法，通过这个注释来说明在调用这个方法之后bean的实例将被清除掉。<br /><br />为了减少描述组件的说明信息，规范组织还采纳了由异常进行配置（configuration-by-exception）的手段，意思是你可以为所有的注释提供一个明确的缺省值，这样多数常规信息就可以据此推断得出。<br /><br />新的持久化模型<br /><br />新的实体bean也是一个加了注释的简单Java对象(POJO)。一旦它被EntityManager访问它就成为了一个持久化对象，并且成为了持久化上下文（context）的一部分。一个持久化上下文与一个事务上下文是松耦合的；严格的讲，它隐含的与一个事务会话共存。<br /><br />实体关系也是通过注释来定义的，O/R映射也是，并提供几种不同的数据库规范操作，在EJB2.1中这些要通过开发人员自己的设计模式或者其它技术来完成的（比如，自增长主键策略）。<br /><br />深入研究<br /><br />现在是时候详细了解EJB3.0草案了。让我们开始探讨所有EJB中四种企业级bean，并看看他们在新的规范中是什么样子。<br /><br />无状态回话bean<br /><br />在EJB3.0规范中，写一个无状态回话bean(SLSB)只需要一个简单的Java文件并在类层加上@Stateless注释就可以了。这个bean可以扩展javax.ejb.SessionBean接口，但这些不是必须的。<br /><br />一个SLSB不再需要home接口，没有哪类EJB再需要它了。Bean类可以实现业务接口也可以不实现它。如果没有实现任何业务接口，业务接口会由任意public的方法产生。如果只有几个业务方法会被暴露在业务接口中，这些方法可以使用@BusinessMethod注释。缺省情况下所有产生的接口都是local（本地）接口，你也可以使用@Remote注释来声明这个接口为remote（远程）接口。<br /><br />下面的几行代码就可以定义一个HelloWorldbean了。而在EJB2.1中同样的bean至少需要两个接口，一个实现类和几个空的实现方法，再加上部署描述符。<br /><br />import javax.ejb.*;<br /><br />/**<br />* A stateless session bean requesting that a remote business<br />* interface be generated for it.<br />*/<br />@Stateless<br />@Remote<br />public class HelloWorldBean {<br />   public String sayHello() {<br />      return "Hello World!!!";<br />   }<br />}<br /><br />有状态回话bean<br /><br />除了几个SFSB的特别说明之外，有状态回话bean(SFSB)和SLSB一样精简：<br /><br />l         一个SFSB应该有一个方法来初始化自己（在EJB2.1中是通过ejbCreate()来实现的）。在EJB3.0的规范中建议这些初始化操作可以通过自定义方法完成，并把他们暴露在业务接口中。在使用这个bean之前由客户端来调用相应的初始化方法。目前规范组织就是否提供一个注释来标记某个方法用于初始化还存在争议。<br /><br />l         Bean的提供者可以用@Remove注释来标记任何SFSB的方法，以说明这个方法被调用之后bean的实例将被移除。同样，规范组织仍然在讨论是否要有一种机制来处理这种特殊的情况，即当这个方法出现异常的情况下bean的实例是否被移除。<br /><br />下面是对以上问题我个人的观点：<br /><br />l         是否应该有一个注释来标明一个方法进行初始化呢？我的观点是――应该有，这样容器就可以在调用其他方法之前至少调用一个方法来进行初始化。这不仅可以避免不必要的错误(由于没有调用初始化方法)而且可以使容器更明确的判断是否可以重用SFSB实例。我暂且把这个问题放一放，规范组织只考虑为一个方法提供一个注释来声明它是一个初始化方法。<br /><br />l         对于第二个问题我的观点也是肯定的。这有利于Bean的提供者合客户端程序对其进行控制。只有一个遗留的问题：那就是一旦调用这个方法失败，是否能移除这个bean 的实例？答案是不能，但是它将会在回话结束的时候被移除。<br /><br />消息驱动Bean<br /><br />消息驱动Bean是唯一一种必须实现一个业务接口的Bean。这个接口指出bean支持的是哪一种消息系统。对于以JMS为基础的MDB来说，这个接口是javax.jms.MessageListener。注意MDB业务接口不是一个真正意义上的业务接口，它只是一个消息接口。<br /><br />实体Bean<br /><br />l         实体Bean使用@Entity注释来标记，所有实体bean中的属性/字段不必使用@Transient注释来标记。实体bean的持久化字段可以通过JavaBean-style机制或者声明为public/protected字段来实现。<br /><br />l         实体bean可以使用助手类来描述其状态，但是这些类的实例并没有持久化唯一性（persistent identity）的特性(即，唯一标识这个bean的字段等)，实际上这些助手类与他们的实体bean实例是紧密结合的；并且这些对象还是以非共享方式来访问实体对象的。<br /><br />实体关联<br /><br />EJB3.0同时支持Bean之间双向的合单向的关联，它们可以是一对一、一对多、多对一或者是多对多的关联。然而双向关联的两端还要分为自身端（owning side）和对方端（inverse side）不同的端。自身端负责向数据库通告关联的变更。对于多对多的关联自身端必须明确的声明。实际上对方端通过isInverse=true进行注释（由此自身端就不必说明了而是由另一段推断出）。看来上面的描述，规范组织还能说让EJB变的简单了吗？<br /><br />O/R映射<br /><br />EJB3.0中的O/R映射模型也有了重要的改变，它从原来的abstract-persistence-schema-based变成了现在的Hibernate-inspired模式。尽管目前规范组织还在就此进行讨论但是一个明确的模型将会出现在下一个版本的草案中。<br /><br />举例来说，O/R映射模型将通过bean类中的注释来声明。而且此方法还会指出对应的具体表和字段。O/R映射模型提供了一套自有的SQL；而且除了提供一些基本的SQL外还支持某些高层开发的功能。比如，有一个通过@Column注释声明的字段columnDefinition，那么可以写这样的SQL：columnDefinition="BLOB NOT NULL"<br /><br />客户端程序模型<br /><br />一个EJB客户端可以通过@Inject注释以一种“注入”的方式获得一个bean的业务接口引用。你也可以使用另一个注释@javax.ejb.EJBContext.lookup()来完成上面的操作，但是规范中没有告诉我们一个普通的Java客户端怎样获得一个Bean的实例，因为这个普通的Java客户端是运行在一个客户端容器中，它无法访问@javax.ejb.EJBContex对象。现在还有另外一种机制来完成上面的工作那就是使用一个超级上下文环境对象：@javax.ejb.Context()。但是规范中没有指出该如何在客户端中使用这个对象。<br /><br />EJB QL<br /><br />EJB QL可以通过@NamedQuery来注释。这个注释有两个成员属性分别是name和queryString.一旦定义了这些属性，就可以通过EntityManager.createNamedQuery(name)来指向这个查询。你也可以创建一个标准的JDBC风格的查询并使用EntityManager.createQuery(ejbqlString)或EntityManager.createNativeQuery(nativeSqlString)(这个方法用于执行一个本地查询)来执行查询。<br /><br />EJB QL有两个地方可以定义其参数。javax.ejb.Query接口提供了定义参数、指向查询、更新数据等等方法。下面是一个EJBQL指向查询的例子：<br /><br />.. ..<br />@NamedQuery(<br />name="findAllCustomersWithName",<br />queryString="SELECT c FROM Customer c WHERE c.name LIKE :custName"<br />)<br />.. ..<br />@Inject public EntityManager em;<br />customers = em.createNamedQuery("findAllCustomersWithName")<br />.setParameter("custName", "Smith")<br />.listResults();<br /><br />下面列出了一些EJB QL的增强特性：<br /><br />l         支持批量更新和删除。<br /><br />l         直接支持内连接和外连接。FETCH JOIN运行你指出关联的实体，Order可以指定只查询某个字段。<br /><br />l         查询语句可以返回一个以上的结果值。实际上，你可以返回一个依赖的类比如下面这样：SELECT new CustomerDetails(c.id, c.status, o.count)<br />      FROM Customer c JOIN c.orders o<br />      WHERE o.count &gt; 100<br /><br />l         支持group by 和having。<br /><br />l         支持where子句的嵌套子查询。<br /><br />在提交的EJB3.0草案中，EJB QL与标准SQL非常的接近。实际上规范中甚至直接支持本地的SQL(就像我们上面提到的那样)。这一点对某些程序员来说也许有些不是很清楚，我们将在下面进行更详细的讲解。<br /><br />多样性<br /><br />方法许可(Method permissions)可以通过@MethodPermissions或@Unchecked注释来声明；同样的，事务属性也可以通过@TransactionAttribute注释来声明。规范中仍然保留资源引用和资源环境引用。这些一样可以通过注释来声明，但是有一些细微的差别。比如，上下文(context)环境要通过注入工具控制。容器根据bean对外部环境引用自动初始化一个适当的已经声明的实例变量。比如，你可以象下面这样获得一个数据源（DataSource）：<br /><br />@Resource(name="myDataSource") //Type is inferred from variable<br />public DataSource customerDB;<br /><br />在上面的例子中如果你不指定引用资源的名称(name)那么其中的customerDB会被认为是默认值。当所有的引用属性都可得到时，@Injec注释就可以这样写：<br /><br />@Inject public DataSource customerDB;<br /><br />容器负责在运行时初始化customerDB数据源实例。部署人员必须在此之前在容器中定义好这些资源属性。<br /><br />更好的消息是：那些以前必须检测的异常将一去不复返。你可以声明任意的应用程序异常，而不必在再抛出或捕获其他类似CreateException和FinderException这样的异常。容器会抛出封装在javax.ejb.EJBException中的系统级异常或者只在必要时候抛出IllegalArgumentException或IllegalStateException异常。<br /><br />EJB文件处理模式<br /><br />在我们结束本节之前，让我的快速的浏览一下容器提供商在EJB处理模式方面可能的变更。规范中对此并没有明确的表态，但我可以想到至少两种模式。<br /><br />l         一种办法是首先利用EJB文件生成类似于EJB2.1部署模式的文件（包括必要的接口和部署描述符）然后再用类似于EJB2.1的方式来部署这个EJB组件。当然，这样产生的部署描述<img src ="http://www.blogjava.net/jelver/aggbug/77473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">冰河快狼</a> 2006-10-26 21:00 <a href="http://www.blogjava.net/jelver/articles/77473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>