﻿<?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-/* Author: J@mes */</title><link>http://www.blogjava.net/James-Wei/</link><description>Warning:This site contains ADULT content, ensure that you've been 18 years old! If NOT,please leave immediately.
</description><language>zh-cn</language><lastBuildDate>Wed, 29 Apr 2026 16:53:20 GMT</lastBuildDate><pubDate>Wed, 29 Apr 2026 16:53:20 GMT</pubDate><ttl>60</ttl><item><title>EJB3学习总结（2）</title><link>http://www.blogjava.net/James-Wei/archive/2009/06/06/280366.html</link><dc:creator>J@mes</dc:creator><author>J@mes</author><pubDate>Sat, 06 Jun 2009 13:11:00 GMT</pubDate><guid>http://www.blogjava.net/James-Wei/archive/2009/06/06/280366.html</guid><wfw:comment>http://www.blogjava.net/James-Wei/comments/280366.html</wfw:comment><comments>http://www.blogjava.net/James-Wei/archive/2009/06/06/280366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/James-Wei/comments/commentRss/280366.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/James-Wei/services/trackbacks/280366.html</trackback:ping><description><![CDATA[总结（2）是针对EJB3的事务和安全中的容器管理事务（CMT），BMT及安全部分放在总结（3）中。<br />
完全是自己学习的心得，还请前辈们指点。<br />
<br />
&nbsp;
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">EJB3</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: 'Times New Roman'">的事务与安全</span><span lang="EN-US" style="font-family: Monaco; mso-hansi-font-family: 'Times New Roman'"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">EJB3</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的是事务也符合</span><span lang="EN-US" style="font-family: Monaco">ACID</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，即原子性、一致性、隔离型、持久性。这些特性与数据库事务一致，需要强调的是一致性，在事务开始前，系统是处于一种遵守业务规则和约束的一致状态下，那么在事务提交或回滚之后，系统也必须维持这种一致性状态。在事务进行过程中不必处于不一致性状态，事务在这里就像一个沙箱（</span><span lang="EN-US" style="font-family: Monaco">sand-box</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">）。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">在</span><span lang="EN-US" style="font-family: Monaco">EJB</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中，事务也具有隔离级别的控制，但一般不用通过</span><span lang="EN-US" style="font-family: Monaco">EJB</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">容器来控制，而是在数据库资源这一级别来进行控制。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">要知道在</span><span lang="EN-US" style="font-family: Monaco">EJB</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">容器中，代码层面的所有操作最终都是转化为两级的数据库操作，比如锁定和解锁数据库中的某行或某张表。事务日志来反映事务的变化，开始事务日志代表事务的开始，应用日志代表以提交该事务来结束，相反放弃日志就代表回滚事务而结束。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">资源管理器（</span><span lang="EN-US" style="font-family: Monaco">Resource Manager</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">）的概念是管理特定某种资源的事务的组件。这个概念不仅包括关系数据库系统，也可以使消息服务器或其他业务系统。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">如果只涉及一种单一资源的事务就称为</span><span lang="EN-US" style="font-family: Monaco">local transaction</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">本地事务，相反大多数企业应用都是需要涉及多种不同的资源。这时候就需要一种类型的组件来管理事务中多种资源，这个组件称为事务管理器（</span><span lang="EN-US" style="font-family: Monaco">Transaction Manager</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">），它在多个管理各自资源事务的资源管理之间进行协调和控制。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">分布式的事务管理是通过一种称为两段式提交（</span><span lang="EN-US" style="font-family: Monaco">two-phase commit</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">）的机制来完成。现在最为流行的分布式事务协议是</span><span lang="EN-US" style="font-family: Monaco">XA</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">协议（</span><span lang="EN-US" style="font-family: Monaco">XA Protocol</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">），</span><span lang="EN-US" style="font-family: Monaco">JavaEE</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">就是通过该协议来完成分布式应用中的事务管理。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">事务管理</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">JavaEE</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中事务使用</span><span lang="EN-US" style="font-family: Monaco">JTA</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">（</span><span lang="EN-US" style="font-family: Monaco">Java Transaction API</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，是建立在</span><span lang="EN-US" style="font-family: Monaco">Java Transaction Service</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">之上的服务），即</span><span lang="EN-US" style="font-family: Monaco">javax.tranaction.UserTransaction</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">接口，容器在后台会自动管理大多数事务细节，</span><span lang="EN-US" style="font-family: Monaco">EJB</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">开发者只需控制开始和停止事务、建立事务边界（</span><span lang="EN-US" style="font-family: Monaco">transaction boundary</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">）以及是否提交</span><span lang="EN-US" style="font-family: Monaco">/</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">回滚业务即可。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">在</span><span lang="EN-US" style="font-family: Monaco">EJB3</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中提供了两种具体的事务方式，即容器管理的事务（</span><span lang="EN-US" style="font-family: Monaco">Container-managed transaction</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">）和</span><span lang="EN-US" style="font-family: Monaco">bean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">管理的事务（</span><span lang="EN-US" style="font-family: Monaco">Bean-managed transaction</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，</span><span lang="EN-US" style="font-family: Monaco">BMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">）。其中前者是使用声明式地或通过部署描述符来管理事务；后者需要以显式编码的方式来管理。但需要注意的是在</span><span lang="EN-US" style="font-family: Monaco">EJB3</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中，只有</span><span lang="EN-US" style="font-family: Monaco">SessionBean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">和</span><span lang="EN-US" style="font-family: Monaco">MessageDrivenBean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">才支持</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">和</span><span lang="EN-US" style="font-family: Monaco">BMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，</span><span lang="EN-US" style="font-family: Monaco">JPA</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中并不直接依赖</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">或</span><span lang="EN-US" style="font-family: Monaco">BMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">。但是当然，在任何</span><span lang="EN-US" style="font-family: Monaco">JavaEE</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">容器中都可透明得插入</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">或</span><span lang="EN-US" style="font-family: Monaco">BMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的事务环境。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">EJB3</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中管理事务最简单灵活的方式是采用容器管理事务，即</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">容器管理的事务，顾名思义，容器来做&#8220;事务开始、事务提交或回滚&#8221;。容器在调用方法前开始</span><span lang="EN-US" style="font-family: Monaco">JTA</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">事务，接着会调用业务方法，最后根据调用中发生的情况去决定是提交事务还是回滚事务。使用</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">事务管理，只需关注</span><span lang="EN-US" style="font-family: Monaco">@TransactionManagement</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">和</span><span lang="EN-US" style="font-family: Monaco">@TransactionAttribute</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">注解，同时通过</span><span lang="EN-US" style="font-family: Monaco">EJBContext</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的方法来回滚事务。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">1</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">．</span><span lang="EN-US" style="font-family: Monaco">@TransactionMangement</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">注解用于向容器标识该</span><span lang="EN-US" style="font-family: Monaco">bean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的事务管理是使用</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">还是</span><span lang="EN-US" style="font-family: Monaco">BMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，是通过该标签中的</span><span lang="EN-US" style="font-family: Monaco">value</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">属性来指明</span><span lang="EN-US" style="font-family: Monaco">TransactionManagementType</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的枚举值。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">2</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">．</span><span lang="EN-US" style="font-family: Monaco">@TransactionAttribute</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">注解，尽管由容器为我们来管理事务的各种细节，但是仍然需要通过该注解来告知容器如何去自动管理。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">对事务的管理可以在包装</span><span lang="EN-US" style="font-family: Monaco">bean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的方法时开始，也可以从调用者的事务中进行</span><span lang="EN-US" style="font-family: Monaco">join</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">开始。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">TransactionAttributeType</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">有几个枚举值：</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="font-family: Monaco; mso-bidi-font-family: 宋体"><span style="mso-list: Ignore">（1）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: Monaco">REQUIRED</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">：如果调用者没有事务，容器则创建新事务；如果调用者具有事务，容器则连接</span><span lang="EN-US" style="font-family: Monaco">join</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">调用者事务。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="font-family: Monaco; mso-bidi-font-family: 宋体"><span style="mso-list: Ignore">（2）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: Monaco">REQUIRED_NEW</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">：如果调用者没有事务，容器就创建新事务；如果调用者有事务，容器暂停原来事务，并创建新的事务。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="font-family: Monaco; mso-bidi-font-family: 宋体"><span style="mso-list: Ignore">（3）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: Monaco">SUPPORTS</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">：如果调用者没有事务，容器就不创建事务；反之则</span><span lang="EN-US" style="font-family: Monaco">join</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">并使用调用者的事务。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="font-family: Monaco; mso-bidi-font-family: 宋体"><span style="mso-list: Ignore">（4）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: Monaco">MANDATORY</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">：如果调用者没有事务，容器抛出</span><span lang="EN-US" style="font-family: Monaco">javax.ejb.EJBTransactionRequiredException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">异常；反之则连接并使用调用者的事务。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="font-family: Monaco; mso-bidi-font-family: 宋体"><span style="mso-list: Ignore">（5）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: Monaco">NOT_SUPPORTED</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">：如果调用者没有事务，容器便不使用事务调用方法；反之则暂停调用者事务以</span><span lang="EN-US" style="font-family: Monaco">non-transactional</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的方式调用方法。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 36.0pt; mso-list: l0 level1 lfo1"><span lang="EN-US" style="font-family: Monaco; mso-bidi-font-family: 宋体"><span style="mso-list: Ignore">（6）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: Monaco">NEVER</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">：如果调用者没有事务，容器直接调用方法；反正抛出</span><span lang="EN-US" style="font-family: Monaco">javax.ejb.EJBException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">异常。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="font-family: Monaco; mso-fareast-font-family: Monaco; mso-bidi-font-family: Monaco"><span style="mso-list: Ignore">a.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">对于第</span><span lang="EN-US" style="font-family: Monaco">1</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">种情况，适合的场景是从</span><span lang="EN-US" style="font-family: Monaco">non-transactional</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的</span><span lang="EN-US" style="font-family: Monaco">Web</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">层调用</span><span lang="EN-US" style="font-family: Monaco">bean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">方法，如果方法调用出现异常，那么容器不仅会</span><span lang="EN-US" style="font-family: Monaco">rollback</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">整个事务，同时也会向调用者抛出</span><span lang="EN-US" style="font-family: Monaco">javax.transaction.RollbackException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">异常，以通知调用者事务已被回滚了。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="font-family: Monaco; mso-fareast-font-family: Monaco; mso-bidi-font-family: Monaco"><span style="mso-list: Ignore">b.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">第</span><span lang="EN-US" style="font-family: Monaco">2</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">种情况中，始终需要容器去创建新的事务，对于调用者原有的事物，容器就会暂停它，直到方法调用返回为止就恢复原有事务。这样的结果就是方法调用所创建的新事务无论成功与否，都不会对调用者原有的事务造成影响。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="font-family: Monaco; mso-fareast-font-family: Monaco; mso-bidi-font-family: Monaco"><span style="mso-list: Ignore">c.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: Monaco">SUPPORT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">选项表示本质上容器将会按照调用者的事务情况来处理，通常的场景是用于一些只读型的操作，比如检索数据记录等。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="font-family: Monaco; mso-fareast-font-family: Monaco; mso-bidi-font-family: Monaco"><span style="mso-list: Ignore">d.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: Monaco">MANDATORY</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">表示对容器对事务的强制性要求，如果调用者存在事务，容器就</span><span lang="EN-US" style="font-family: Monaco">join</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">并使用调用者事务；但如果调用者没有事务环境，就会抛出</span><span lang="EN-US" style="font-family: Monaco">EJBTransactionRequiredException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">异常。这种选项适合于如果方法调用失败进行回滚时也保证调用者环境的失败。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="font-family: Monaco; mso-fareast-font-family: Monaco; mso-bidi-font-family: Monaco"><span style="mso-list: Ignore">e.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">对于</span><span lang="EN-US" style="font-family: Monaco">NOT_SUPPORT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，容器处理的本质是要求不能在事务环境下调用</span><span lang="EN-US" style="font-family: Monaco">bean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">方法。如果调用者存在事务，容器会先暂停它，然后开始方法调用，在返回后恢复调用者的事务。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt; mso-list: l1 level1 lfo2"><span lang="EN-US" style="font-family: Monaco; mso-fareast-font-family: Monaco; mso-bidi-font-family: Monaco"><span style="mso-list: Ignore">f.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family: Monaco">NEVER</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">表明在</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中，容器不能允许从事务性环境中调用</span><span lang="EN-US" style="font-family: Monaco">bean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">方法，否则会抛出</span><span lang="EN-US" style="font-family: Monaco">EJBException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">异常。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">对于前面这六种</span><span lang="EN-US" style="font-family: Monaco">TransactionAttributeType</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，</span><span lang="EN-US" style="font-family: Monaco">MDB</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">并不是全部都支持，它支持</span><span lang="EN-US" style="font-family: Monaco">REQUIRED</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">和</span><span lang="EN-US" style="font-family: Monaco">NOT_SUPPORT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">两种。这一点与</span><span lang="EN-US" style="font-family: Monaco">MDB</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的特性有关：客户端无法直接调用</span><span lang="EN-US" style="font-family: Monaco">MDB</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，所以事务属性中的</span><span lang="EN-US" style="font-family: Monaco">SUPPORT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">、</span><span lang="EN-US" style="font-family: Monaco">REQUIRED_NEW</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">和</span><span lang="EN-US" style="font-family: Monaco">MANDATORY</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">就没有意义。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">事务管理的真正机制</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">很重要的一点：</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">方法要求容器回滚事务并不是立即进行的，而是向容器设置回滚标识，在事务结束的时候，容器检查该标志，如果不需回滚则提交该事务，如果需要回滚则进行。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">通过</span><span lang="EN-US" style="font-family: Monaco">EJBContext</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">或其子类：</span><span lang="EN-US" style="font-family: Monaco">SessionContext</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">和</span><span lang="EN-US" style="font-family: Monaco">MessageDrivenContext</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的</span><span lang="EN-US" style="font-family: Monaco">setRollbackOnly()</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">方法，将回滚标志位置为</span><span lang="EN-US" style="font-family: Monaco">true</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，当方法调用结束时，容器检查该状态以判断是否提交事务或是回滚事务。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">需要注意的一点是，本质上，使用</span><span lang="EN-US" style="font-family: Monaco">EJBContext</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">进行设置标志位时，它是作为底层事务的一个上层抽象代理。所以使用时，必须保证有底层事务存在，也就是说必须在</span><span lang="EN-US" style="font-family: Monaco">REQUIRED,REQUIRED_NEW,MADATORY</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">这三种事务属性下使用！因为这三种事务属性都可以使容器保证底层事务的存在，即无论方法调用者是否存在事务环境，容器都会创建新事务。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">与</span><span lang="EN-US" style="font-family: Monaco">setRollbackOnly()</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">方法对应的是</span><span lang="EN-US" style="font-family: Monaco">getRollbackOnly()</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">方法，该方法返回当前</span><span lang="EN-US" style="font-family: Monaco">EJBContext</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中回滚标志位的状态。该方法在业务处理中十分有用，考虑这样一个场景：</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">在进行一段非常长的资源密集型操作前如果前事务的前部分已经失败，那就是在一个注定要回滚的事务上付出很多代价。所以在这类操作之前应该先</span><span lang="EN-US" style="font-family: Monaco">check</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">一下</span><span lang="EN-US" style="font-family: Monaco">rollbackOnly</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">是否已经置为</span><span lang="EN-US" style="font-family: Monaco">true</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">此外，处理该标志位状态的代码经常分布在业务逻辑的</span><span lang="EN-US" style="font-family: Monaco">catch</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">块中，如果</span><span lang="EN-US" style="font-family: Monaco">catch</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">了某种</span><span lang="EN-US" style="font-family: Monaco">exception</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，则一边记录进</span><span lang="EN-US" style="font-family: Monaco">log</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，一边通过</span><span lang="EN-US" style="font-family: Monaco">set</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">方法置状态位。在</span><span lang="EN-US" style="font-family: Monaco">EJB3</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中，可以通过</span><span lang="EN-US" style="font-family: Monaco">@ApplicationException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">注解使得&#8220;捕获异常转化为事务回滚&#8221;变成透明的机制。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">@AplicationException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">注解</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">@javax.ejb.ApplicationException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">该注解可以用来控制事务性输出，将要抛出的异常类型在定义时加上该标签，同时设置该标签的</span><span lang="EN-US" style="font-family: Monaco">rollback</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">属性，即</span><span lang="EN-US" style="font-family: Monaco">@ApplicationException(rollback=true/false)</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">。应用异常（</span><span lang="EN-US" style="font-family: Monaco">ApplicationException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">）是希望调用者或客户端处理的，一般认为除了</span><span lang="EN-US" style="font-family: Monaco">java.rmi.RemoteException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">和</span><span lang="EN-US" style="font-family: Monaco">java.lang.RuntimeException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">之外都是应用异常。而从上述两种异常继承出的子类异常都被认为是系统异常，这种异常不会传递给调用者或客户端而是</span><span lang="EN-US" style="font-family: Monaco">wrapped</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">在</span><span lang="EN-US" style="font-family: Monaco">EJBException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">中。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">添加此注解的异常无论是</span><span lang="EN-US" style="font-family: Monaco">checked exception</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">还是</span><span lang="EN-US" style="font-family: Monaco">unchecked exception</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">（比如运行时异常），都会被认为是应用异常（</span><span lang="EN-US" style="font-family: Monaco">application exception</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">），从而传递给方法调用者或客户端。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">默认情况下，所有</span><span lang="EN-US" style="font-family: Monaco">checked exception</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">或所有被注解为应用异常的</span><span lang="EN-US" style="font-family: Monaco">checked/unchecked exception</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，都不会以</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的方式回滚，如果把</span><span lang="EN-US" style="font-family: Monaco">rollback</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">属性设置为</span><span lang="EN-US" style="font-family: Monaco">true</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，则会通知容器失败时进行事务回滚，并且是在把应用异常传递给调用者或客户端之前进行的。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">如果有未预料的</span><span lang="EN-US" style="font-family: Monaco">unchecked exception</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，比如</span><span lang="EN-US" style="font-family: Monaco">ArrayOutOfBoundsException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">或</span><span lang="EN-US" style="font-family: Monaco">NullPointerException</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">，容器仍然会回滚</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">事务，但是在这种情况下，容器会认为</span><span lang="EN-US" style="font-family: Monaco">bean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">处在了一种</span><span lang="EN-US" style="font-family: Monaco">inconsistent</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">的情况下，会进而销毁</span><span lang="EN-US" style="font-family: Monaco">bean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">实例，这是十分消耗资源的，所以</span><span lang="EN-US" style="font-family: Monaco">you should never delibrately use system exceptions.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">使开发人员不必关心</span><span lang="EN-US" style="font-family: Monaco">EJB</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">事务中的大部分细节，当然同时</span><span lang="EN-US" style="font-family: Monaco">CMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">能提供对事务的控制级别也更少，这一点</span><span lang="EN-US" style="font-family: Monaco">Bean</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">管理的事务（</span><span lang="EN-US" style="font-family: Monaco">BMT</span><span style="font-family: 宋体; mso-ascii-font-family: Monaco; mso-hansi-font-family: Monaco">）更适合。</span><span lang="EN-US" style="font-family: Monaco"><o:p></o:p></span></p>
<p class="MsoNormal">&nbsp;</o:p></span></p>
<img src ="http://www.blogjava.net/James-Wei/aggbug/280366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/James-Wei/" target="_blank">J@mes</a> 2009-06-06 21:11 <a href="http://www.blogjava.net/James-Wei/archive/2009/06/06/280366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EJB3学习总结（1）</title><link>http://www.blogjava.net/James-Wei/archive/2009/05/29/278953.html</link><dc:creator>J@mes</dc:creator><author>J@mes</author><pubDate>Fri, 29 May 2009 14:28:00 GMT</pubDate><guid>http://www.blogjava.net/James-Wei/archive/2009/05/29/278953.html</guid><wfw:comment>http://www.blogjava.net/James-Wei/comments/278953.html</wfw:comment><comments>http://www.blogjava.net/James-Wei/archive/2009/05/29/278953.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/James-Wei/comments/commentRss/278953.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/James-Wei/services/trackbacks/278953.html</trackback:ping><description><![CDATA[作为近期学习EJB3&nbsp; 的一些心得和总结，完全是自己的理解和白话，前辈们请多指教<br />
<p>EJB3学习<span style="font-family: 宋体">总结（1）</span></p>
<p><span style="font-family: 宋体">现状</span></p>
<p>EJB2<span style="font-family: 宋体">得到了较广泛的应用，但真正用对场合的项目不多，那些强调分布式，即业务逻辑和</span>Web<span style="font-family: 宋体">是在分布在不同物理层的大型项目。更多得是使用在中小型</span>web<span style="font-family: 宋体">应用之上。</span></p>
<p>EJB3<span style="font-family: 宋体">在</span>Spring<span style="font-family: 宋体">、</span>Hibernate<span style="font-family: 宋体">等一系列轻量级框架运动的发展后现身了，</span>EJB3<span style="font-family: 宋体">是基于</span>POJO<span style="font-family: 宋体">组件的，同时提供了事务、安全、</span>ORM<span style="font-family: 宋体">和分布式等诸多特点，同时</span>AOP<span style="font-family: 宋体">、</span>DI<span style="font-family: 宋体">及</span>Annotation<span style="font-family: 宋体">等特性也进一步提高了</span>EJB3<span style="font-family: 宋体">的易用性。</span></p>
<p>EJB3<span style="font-family: 宋体">规范</span></p>
<p>EJB3<span style="font-family: 宋体">规范包含</span>3<span style="font-family: 宋体">个技术文档：</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>EJB3 Simplified API</p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>EJB3 Core Contracts &amp; Requirement</p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Java Persistence API</p>
<p>EJB3<span style="font-family: 宋体">组件模型</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Session Bean<span style="font-family: 宋体">：执行业务服务、控制事务及资源访问</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Message Driven Bean<span style="font-family: 宋体">：异步调用，通过</span>JMS<span style="font-family: 宋体">关联消息队列（</span>Queue<span style="font-family: 宋体">）及</span>Topic<span style="font-family: 宋体">来响应外部事件</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Entity<span style="font-family: 宋体">：具有唯一标示的实体，是持久化的基础。</span></p>
<p>SessionBean<span style="font-family: 宋体">和</span>MDBean<span style="font-family: 宋体">统称为</span>Enterprise Bean<span style="font-family: 宋体">，这点不同于</span>EJB2<span style="font-family: 宋体">规范。</span>EntityBean<span style="font-family: 宋体">已经划分由持久化</span>Provider<span style="font-family: 宋体">去管理和控制，不再由</span>EJB<span style="font-family: 宋体">容器管理。</span></p>
<p>EJB3<span style="font-family: 宋体">框架</span></p>
<p><span style="font-family: 宋体">它提供了对</span>EJB3<span style="font-family: 宋体">组件的各种支持，包括容器事务、安全服务、资源池的管理（包括线程池、连接池、实例池）以及组件生命周期的管理、并发支持等。</span></p>
<p>EJB3<span style="font-family: 宋体">的核心</span>features</p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">声明式的元数据：通过</span>Java5<span style="font-family: 宋体">的</span>Annotation<span style="font-family: 宋体">或</span>XML<span style="font-family: 宋体">来声明式地去指定</span>Enterprise Bean<span style="font-family: 宋体">和</span>Entity Bean<span style="font-family: 宋体">的行为和特性。如果同时使用两种方式时，</span>XML<span style="font-family: 宋体">描述具有更高的优先级。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">按异常配置：对于大量可使用</span>default<span style="font-family: 宋体">配置的地方都可以省去繁琐的配置，只有需要不按默认行为的才需要显式得通过注解或</span>XML<span style="font-family: 宋体">来进行描述。强调用户只有需要配置时才进行配置，可以使代码更为简洁。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">良好的可伸缩性：</span>EJB3<span style="font-family: 宋体">的实现中在三个方面保证了良好的伸缩性，（</span>1<span style="font-family: 宋体">）通过资源池最大程度上对重新对象的重用；（</span>2<span style="font-family: 宋体">）使用持久化及缓存避免重复查询和重复创建实体；（</span>3<span style="font-family: 宋体">）优化的锁定策略，避免对</span>DB<span style="font-family: 宋体">的并发锁定。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>JTA<span style="font-family: 宋体">（</span>Java Transaction API<span style="font-family: 宋体">）定义了分布式事务的标准</span>API<span style="font-family: 宋体">。</span>EJB<span style="font-family: 宋体">容器作为</span>JTA<span style="font-family: 宋体">的事务管理器。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">通过声明的方式来控制方法级别的访问控制，达到多层安全性。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">实体</span>Bean<span style="font-family: 宋体">被替换成</span>POJO<span style="font-family: 宋体">，简单、轻量，不用再去实现专门的接口，同时可以脱离</span>EJB<span style="font-family: 宋体">容器。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">7.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>SessionBean<span style="font-family: 宋体">也更加灵活，不再需要主接口（</span>Home Interface<span style="font-family: 宋体">）</span>.</p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">8.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">依赖注入（</span>dependency injection<span style="font-family: 宋体">），可以通过</span>Annotation<span style="font-family: 宋体">或</span>XML<span style="font-family: 宋体">的方式将依赖数据&#8220;推（</span>push<span style="font-family: 宋体">）&#8221;到</span>bean<span style="font-family: 宋体">。例如：将</span>EntityManager<span style="font-family: 宋体">注入到</span>SessionBean<span style="font-family: 宋体">中，以使会话可以与持久化单元进行交互。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">9.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">拦截器和回调（</span>Call-back<span style="font-family: 宋体">）：通过拦截器来完成某些回调方法。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">10.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp; </span><span style="font-family: 宋体">对于</span>SessionBean<span style="font-family: 宋体">和</span>MDB<span style="font-family: 宋体">，不在需要主方法（</span>ejbCreate()<span style="font-family: 宋体">），使用默认构造器来替代。同时也不需要再扩展专有接口。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">11.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp; </span><span style="font-family: 宋体">对于</span>EntityBean<span style="font-family: 宋体">，主接口（</span>Home interface<span style="font-family: 宋体">）也被替换成</span>EntityManager<span style="font-family: 宋体">，后者是一个单例实例工厂，可以管理实体</span>Bean<span style="font-family: 宋体">的生命周期。</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">12.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp; </span>EJB3<span style="font-family: 宋体">的分布式计算模型：</span>EJB3<span style="font-family: 宋体">也基于</span>RMI<span style="font-family: 宋体">远程服务，远程接口方法按值传递以提供粗粒度的模型。</span></p>
<p>EJB3<span style="font-family: 宋体">角色</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">定义</span>Enterprise Bean<span style="font-family: 宋体">及相关</span>meta-data<span style="font-family: 宋体">的三种角色：</span></p>
<p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 36.0pt">（1）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">企业</span>Bean<span style="font-family: 宋体">提供者（</span>Enterprise Bean provider<span style="font-family: 宋体">），负责去定义和实现业务逻辑和结构；负责定义实体的持久化结构及互相关系。</span></p>
<p style="margin-left: 36pt; text-indent: -36pt; tab-stops: list 36.0pt">（2）<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">应用装配者（</span>Application assembler<span style="font-family: 宋体">）。</span></p>
<p>EJB3<span style="font-family: 宋体">的会话</span>Bean</p>
<p>EJB3<span style="font-family: 宋体">中，</span>SessionBean<span style="font-family: 宋体">包括两种类型，</span>Stateful SessionBean<span style="font-family: 宋体">和</span>Stateless SessionBean<span style="font-family: 宋体">。</span></p>
<p><span style="font-family: 宋体">顾名思义，</span>Stateless SessionBean<span style="font-family: 宋体">不需维持客户请求的会话状态；而</span>Stateful SessionBean<span style="font-family: 宋体">则需要维持特定客户请求的会话状态，同时</span>bean<span style="font-family: 宋体">实例也是用客户请求绑定的。</span></p>
<p>Stateless SessionBean</p>
<p><span style="font-family: 宋体">无状态会话</span>Bean<span style="font-family: 宋体">由两个元素组成：业务接口，用来定义所提供的服务；</span>bean<span style="font-family: 宋体">类，是对服务接口的实现。注意此处，不需像</span>EJB2.x<span style="font-family: 宋体">中分别实现</span>EJBObject<span style="font-family: 宋体">和</span>SessionBean<span style="font-family: 宋体">接口。</span></p>
<p><span style="font-family: 宋体">通过示例，通过定义本地接口和（或）远程接口来定义业务接口，这里</span>Local<span style="font-family: 宋体">接口和</span>Remote<span style="font-family: 宋体">接口的选择遵循一个原则：如果业务的请求者与</span>SessionBean<span style="font-family: 宋体">处在同一个</span>JVM<span style="font-family: 宋体">中，则可以使用本地接口，反之则必须使用远程接口。</span></p>
<p><span style="font-family: 宋体">原则上，如果同时使用了本地接口和远程接口，则必须保证二者定义的接口一致，同时由实现的</span>Bean<span style="font-family: 宋体">实现这些方法。</span></p>
<p><span style="font-family: 宋体">无状态会话</span>Bean<span style="font-family: 宋体">无需实现</span>EJB<span style="font-family: 宋体">特定的接口或扩展类，只需在类级别使用注解——</span>@Stateless<span style="font-family: 宋体">即可。同时也在本地接口及远程接口的类级别添加注解——</span>@Local<span style="font-family: 宋体">和</span>@Remote<span style="font-family: 宋体">。</span></p>
<p><span style="font-family: 宋体">通过前面对</span>EJB3<span style="font-family: 宋体">特性的介绍，可以知道</span>EJB3<span style="font-family: 宋体">对</span>DI<span style="font-family: 宋体">（</span>Dependency Injection<span style="font-family: 宋体">）的良好支持！在</span>EJB3<span style="font-family: 宋体">中，可以将各类资源注入到会话</span>Bean<span style="font-family: 宋体">中，这些资源可以是其他的会话</span>Bean<span style="font-family: 宋体">、数据源或者是</span>JMS<span style="font-family: 宋体">中的队列（</span>Queue<span style="font-family: 宋体">）等。要实现依赖注入可以通过添加注解，也可以在</span>XML<span style="font-family: 宋体">配置文件中进行描述，但需注意的是，如果二者都进行的配置则以</span>XML<span style="font-family: 宋体">文件中的描述为准。</span></p>
<p><span style="font-family: 宋体">以注解的方式为例，只需添加</span>@Resource<span style="font-family: 宋体">注解即可，注入可以通过两种方式：实例变量和</span>setter<span style="font-family: 宋体">方法上。</span></p>
<p><span style="font-family: 宋体">回调（</span>Call-back<span style="font-family: 宋体">），通过回调，可以对</span>Bean<span style="font-family: 宋体">在其生命周期内各个阶段进行更细粒度的控制和管理。使用回调方法也很简单，回调方法没有多余的限制，只需添加正确的注解即可。</span></p>
<p><span style="font-family: 宋体">无状态会话</span>Bean<span style="font-family: 宋体">两个主要的用于回调方法的注解分别是：</span>@PostConstruct<span style="font-family: 宋体">和</span>@PreDestroy<span style="font-family: 宋体">。其中</span>@PostConstruct<span style="font-family: 宋体">的方法会在该</span>bean<span style="font-family: 宋体">被实例化后回调执行，但需要注意的是，如果该</span>bean<span style="font-family: 宋体">有配置了需要注入的资源，那该回调方法则会紧跟着资源的注入之后而执行。</span></p>
<p>@PreDestroy<span style="font-family: 宋体">的回调方法则是在容器即将销毁</span>bean<span style="font-family: 宋体">实例之前被调用，主要用来做一些善后的工作，比如对资源的关闭和清理。（补充，在有状态会话</span>Bean<span style="font-family: 宋体">中，该方法是在最后一个带有</span>@Remove<span style="font-family: 宋体">注解的方法调用后才被调用，之后容器销毁</span>bean<span style="font-family: 宋体">实例。）</span></p>
<p><span style="font-family: 宋体">另一个关键的元素是拦截器（</span>Interceptor<span style="font-family: 宋体">），拦截器的使用也很便捷，通过添加正确的注解即可。拦截器的概念与其他</span>JavaEE<span style="font-family: 宋体">的框架或规范中的一致，即拦截业务方法的调用，可以在拦截点附加新的业务逻辑，结合依赖注入特性，可以充分得做到关注点分离（</span>Separation of Concerns<span style="font-family: 宋体">）。</span>Enterprise Bean<span style="font-family: 宋体">中会话</span>Bean<span style="font-family: 宋体">和消息驱动</span>Bean<span style="font-family: 宋体">可以定义拦截器方法。</span></p>
<p><span style="font-family: 宋体">拦截器注解可以添加到方法级别，也可以添加到类级别。被标注的方法在被调用时会被拦截器类拦截，并插队式的先去调用拦截器的方法。对于用到的拦截器类需要添加</span>@Interceptor<span style="font-family: 宋体">注解，如果有多个拦截器则使用</span>@Interceptors<span style="font-family: 宋体">。</span></p>
<p><span style="font-family: 宋体">以</span>@AroundInvoke<span style="font-family: 宋体">注解为例，拦截器方法需要关注</span>InvocationContext<span style="font-family: 宋体">接口，通过它可以获得被拦截的</span>bean<span style="font-family: 宋体">类（</span>Class<span style="font-family: 宋体">）、</span>bean<span style="font-family: 宋体">中的方法（</span>Method<span style="font-family: 宋体">）等，需要强调的是其中的</span>proceed()<span style="font-family: 宋体">方法，通过它将拦截请求往后传递，或者到拦截器链中的下一个，或者是结束拦截调用真正的</span>bean<span style="font-family: 宋体">方法。</span></p>
<p>EJB3<span style="font-family: 宋体">规范中定义了两种类型的异常，分别是应用异常和系统异常。应用异常是业务逻辑中产生的</span>checked exception<span style="font-family: 宋体">；而系统异常则是</span>EJB<span style="font-family: 宋体">系统级产生的异常，同时系统异常都是</span>RemoteException<span style="font-family: 宋体">和</span>RuntimeException<span style="font-family: 宋体">的子类，是</span>unchecked exception<span style="font-family: 宋体">。</span></p>
<p><span style="font-family: 宋体">有状态会话</span>Bean<span style="font-family: 宋体">（</span>Stateful SessionBean<span style="font-family: 宋体">）在特性及细节上与无状态会话</span>Bean<span style="font-family: 宋体">很相似。</span></p>
<p><span style="font-family: 宋体">会话</span>Bean<span style="font-family: 宋体">的用户视图</span></p>
<p><span style="font-family: 宋体">访问会话</span>Bean<span style="font-family: 宋体">的用户视图可以有三种形式：</span></p>
<p style="margin-left: 39pt; text-indent: -18pt; tab-stops: list 39.0pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">通过</span>Remote<span style="font-family: 宋体">接口，远程客户具有位置无关性。</span></p>
<p style="margin-left: 39pt; text-indent: -18pt; tab-stops: list 39.0pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">通过</span>Local<span style="font-family: 宋体">接口，这两种方式中请求方可以是其他的</span>EJB<span style="font-family: 宋体">组件，可以是</span>Servlet<span style="font-family: 宋体">、</span>JSP<span style="font-family: 宋体">等。需要注意的是，本地客户具有位置依赖性。</span></p>
<p style="margin-left: 39pt; text-indent: -18pt; tab-stops: list 39.0pt">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>WebService<span style="font-family: 宋体">方式，可以将会话</span>Bean<span style="font-family: 宋体">发布成为一个</span>WebService<span style="font-family: 宋体">，供客户调用。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">客户请求会话</span>Bean<span style="font-family: 宋体">时，或者通过依赖注入或者通过查找</span>JNDI<span style="font-family: 宋体">，来获得会话</span>Bean<span style="font-family: 宋体">的</span>stub<span style="font-family: 宋体">对象，请求是通过</span>stub<span style="font-family: 宋体">来进行调用的。对于无状态会话</span>Bean<span style="font-family: 宋体">，每次请求将获得新的</span>stub<span style="font-family: 宋体">，而有状态会话</span>Bean<span style="font-family: 宋体">，则在请求方缓存</span>stub<span style="font-family: 宋体">，这样才能使容器知道该返回哪个与客户相关联的</span>bean<span style="font-family: 宋体">实例。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">通过依赖注入获得会话</span>Bean<span style="font-family: 宋体">业务接口的方式是添加注解</span>@EJB<span style="font-family: 宋体">，注意要与</span>@Resource<span style="font-family: 宋体">区分开。</span></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体">相比查找</span>JNDI<span style="font-family: 宋体">，使用注入的方式会更加简洁，通常对于远程请求使用</span>JNDI<span style="font-family: 宋体">更适合。</span></p>
<p><span style="font-family: 宋体">有状态会话</span>Bean<span style="font-family: 宋体">（</span>Stateful SessionBean<span style="font-family: 宋体">）</span></p>
<p><span style="font-family: 宋体">通过实现</span>SessionSynchronization<span style="font-family: 宋体">接口，可以在事务点上获得</span>EJB<span style="font-family: 宋体">容器的通知：</span>afterBegin<span style="font-family: 宋体">，在新事物开始时；</span>beforeCompletion<span style="font-family: 宋体">，在事物提交前；</span>afterCompletion<span style="font-family: 宋体">，在事物执行完之后。</span></p>
<p><span style="font-family: 宋体">有状态会话</span>Bean<span style="font-family: 宋体">中的回调方法除了</span>PostConstruct<span style="font-family: 宋体">和</span>PreDestroy<span style="font-family: 宋体">外，还有</span>PreActivate<span style="font-family: 宋体">和</span>PrePassivate<span style="font-family: 宋体">，分别使用</span>@PreActivate<span style="font-family: 宋体">和</span>@PrePassivate<span style="font-family: 宋体">来注解。</span></p>
<p><span style="font-family: 宋体">前两个回调方法的细节与无状态会话</span>Bean<span style="font-family: 宋体">一致，分别在（</span>1<span style="font-family: 宋体">）实例化</span>Bean<span style="font-family: 宋体">之后并执行完资源注入后执行；（</span>2<span style="font-family: 宋体">）</span>@Remove<span style="font-family: 宋体">方法执行完毕之后。</span></p>
<p><span style="font-family: 宋体">对于有状态会话</span>Bean<span style="font-family: 宋体">中的</span>@Remove<span style="font-family: 宋体">方法，也是一个管理</span>bean<span style="font-family: 宋体">生命周期的方法，调用该方法后，容器将会从实例池中将该</span>bean<span style="font-family: 宋体">删除。</span></p>
<p><span style="font-family: 宋体">带有</span>@PrePassivate<span style="font-family: 宋体">注解的方法会由</span>EJB<span style="font-family: 宋体">容器调用，当某个有状态会话</span>Bean<span style="font-family: 宋体">实例长时间空闲，则容器调用该方法将此</span>bean<span style="font-family: 宋体">实例钝化，并将状态缓存起来。</span></p>
<p><span style="font-family: 宋体">当客户请求再次需要使用被钝化的某</span>bean<span style="font-family: 宋体">实例时，容器调用该</span>bean<span style="font-family: 宋体">的</span>@PreActivate<span style="font-family: 宋体">方法，返回一个创建好的并带有状态的新实例。</span></p>
<p><span style="font-family: 宋体">有状态会话</span>Bean<span style="font-family: 宋体">的拦截器方法需要注意的是，如果实现</span>SessionSynchronization<span style="font-family: 宋体">接口的</span>bean<span style="font-family: 宋体">，</span>afterBegin<span style="font-family: 宋体">始终发生在</span>@AroundInvoke<span style="font-family: 宋体">的任何方法前。</span></p>
<img src ="http://www.blogjava.net/James-Wei/aggbug/278953.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/James-Wei/" target="_blank">J@mes</a> 2009-05-29 22:28 <a href="http://www.blogjava.net/James-Wei/archive/2009/05/29/278953.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>