﻿<?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-一叶笑天-随笔分类-开源技术</title><link>http://www.blogjava.net/zjrstar/category/31938.html</link><description> 雄关漫道真如铁,
 而今迈步从头越。
 从头越,
 苍山如海,
 残阳如血。 </description><language>zh-cn</language><lastBuildDate>Wed, 07 Jan 2009 06:44:08 GMT</lastBuildDate><pubDate>Wed, 07 Jan 2009 06:44:08 GMT</pubDate><ttl>60</ttl><item><title>[转贴]hibernate二级缓存攻略</title><link>http://www.blogjava.net/zjrstar/archive/2009/01/05/249857.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Mon, 05 Jan 2009 02:40:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2009/01/05/249857.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/249857.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2009/01/05/249857.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/249857.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/249857.html</trackback:ping><description><![CDATA[原文地址：http://www.javaeye.com/topic/18904<br />
<br />
很多人对二级缓存都不太了解，或者是有错误的认识，我一直想写一篇文章介绍一下hibernate的二级缓存的，今天终于忍不住了。 <br />
我的经验主要来自hibernate2.1版本，基本原理和3.0、3.1是一样的，请原谅我的顽固不化。 <br />
<br />
hibernate的session提供了一级缓存，每个session，对同一个id进行两次load，不会发送两条sql给数据库，但是session关闭的时候，一级缓存就失效了。 <br />
<br />
二级缓存是SessionFactory级别的全局缓存，它底下可以使用不同的缓存类库，比如ehcache、oscache等，需要设置hibernate.cache.provider_class，我们这里用ehcache，在2.1中就是 <br />
hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider <br />
如果使用查询缓存，加上 <br />
hibernate.cache.use_query_cache=true <br />
<br />
<br />
缓存可以简单的看成一个Map，通过key在缓存里面找value。 <br />
<br />
<strong>Class的缓存</strong> <br />
对于一条记录，也就是一个PO来说，是根据ID来找的，缓存的key就是ID，value是POJO。无论list，load还是iterate，只要读出一个对象，都会填充缓存。但是list不会使用缓存，而iterate会先取数据库select id出来，然后一个id一个id的load，如果在缓存里面有，就从缓存取，没有的话就去数据库load。假设是读写缓存，需要设置： <br />
&amp;lt;cache usage="read-write"/&amp;gt; <br />
如果你使用的二级缓存实现是ehcache的话，需要配置ehcache.xml <br />
&amp;lt;cache name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false" timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true" /&amp;gt; <br />
其中eternal表示缓存是不是永远不超时，timeToLiveSeconds是缓存中每个元素（这里也就是一个POJO）的超时时间，如果eternal="false"，超过指定的时间，这个元素就被移走了。timeToIdleSeconds是发呆时间，是可选的。当往缓存里面put的元素超过500个时，如果overflowToDisk="true"，就会把缓存中的部分数据保存在硬盘上的临时文件里面。 <br />
每个需要缓存的class都要这样配置。如果你没有配置，hibernate会在启动的时候警告你，然后使用defaultCache的配置，这样多个class会共享一个配置。 <br />
当某个ID通过hibernate修改时，hibernate会知道，于是移除缓存。 <br />
这样大家可能会想，同样的查询条件，第一次先list，第二次再iterate，就可以使用到缓存了。实际上这是很难的，因为你无法判断什么时候是第一次，而且每次查询的条件通常是不一样的，假如数据库里面有100条记录，id从1到100，第一次list的时候出了前50个id，第二次iterate的时候却查询到30至70号id，那么30-50是从缓存里面取的，51到70是从数据库取的，共发送1+20条sql。所以我一直认为iterate没有什么用，总是会有1+N的问题。 <br />
（题外话：有说法说大型查询用list会把整个结果集装入内存，很慢，而iterate只select id比较好，但是大型查询总是要分页查的，谁也不会真的把整个结果集装进来，假如一页20条的话，iterate共需要执行21条语句，list虽然选择若干字段，比iterate第一条select id语句慢一些，但只有一条语句，不装入整个结果集hibernate还会根据数据库方言做优化，比如使用mysql的limit，整体看来应该还是list快。） <br />
如果想要对list或者iterate查询的结果缓存，就要用到查询缓存了 <br />
<br />
<strong>查询缓存</strong> <br />
首先需要配置hibernate.cache.use_query_cache=true <br />
如果用ehcache，配置ehcache.xml，注意hibernate3.0以后不是net.sf的包名了 <br />
&amp;lt;cache name="net.sf.hibernate.cache.StandardQueryCache" <br />
&nbsp;&nbsp; maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600" <br />
&nbsp;&nbsp; timeToLiveSeconds="7200" overflowToDisk="true"/&amp;gt; <br />
&amp;lt;cache name="net.sf.hibernate.cache.UpdateTimestampsCache" <br />
&nbsp;&nbsp; maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/&amp;gt; <br />
然后 <br />
query.setCacheable(true);//激活查询缓存 <br />
query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion，可选 <br />
第二行指定要使用的cacheRegion是myCacheRegion，即你可以给每个查询缓存做一个单独的配置，使用setCacheRegion来做这个指定，需要在ehcache.xml里面配置它： <br />
&amp;lt;cache name="myCacheRegion" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="true" /&amp;gt; <br />
如果省略第二行，不设置cacheRegion的话，那么会使用上面提到的标准查询缓存的配置，也就是net.sf.hibernate.cache.StandardQueryCache <br />
<br />
对于查询缓存来说，缓存的key是根据hql生成的sql，再加上参数，分页等信息（可以通过日志输出看到，不过它的输出不是很可读，最好改一下它的代码）。 <br />
比如hql： <br />
from Cat c where c.name like ? <br />
生成大致如下的sql： <br />
select * from cat c where c.name like ? <br />
参数是"tiger%"，那么查询缓存的key*大约*是这样的字符串（我是凭记忆写的，并不精确，不过看了也该明白了）： <br />
select * from cat c where c.name like ? , parameter:tiger% <br />
这样，保证了同样的查询、同样的参数等条件下具有一样的key。 <br />
现在说说缓存的value，如果是list方式的话，value在这里并不是整个结果集，而是查询出来的这一串ID。也就是说，不管是list方法还是iterate方法，第一次查询的时候，它们的查询方式很它们平时的方式是一样的，list执行一条sql，iterate执行1+N条，多出来的行为是它们填充了缓存。但是到同样条件第二次查询的时候，就都和iterate的行为一样了，根据缓存的key去缓存里面查到了value，value是一串id，然后在到class的缓存里面去一个一个的load出来。这样做是为了节约内存。 <br />
可以看出来，查询缓存需要打开相关类的class缓存。list和iterate方法第一次执行的时候，都是既填充查询缓存又填充class缓存的。 <br />
<strong>这里还有一个很容易被忽视的重要问题，即打开查询缓存以后，即使是list方法也可能遇到1+N的问题！</strong>相同条件第一次list的时候，因为查询缓存中找不到，不管class缓存是否存在数据，总是发送一条sql语句到数据库获取全部数据，然后填充查询缓存和class缓存。但是第二次执行的时候，问题就来了，如果你的class缓存的超时时间比较短，现在class缓存都超时了，但是查询缓存还在，那么list方法在获取id串以后，将会一个一个去数据库load！因此，class缓存的超时时间一定不能短于查询缓存设置的超时时间！如果还设置了发呆时间的话，保证class缓存的发呆时间也大于查询的缓存的生存时间。这里还有其他情况，比如class缓存被程序强制evict了，这种情况就请自己注意了。 <br />
<br />
另外，如果hql查询包含select字句，那么查询缓存里面的value就是整个结果集了。 <br />
<br />
当hibernate更新数据库的时候，它怎么知道更新哪些查询缓存呢？ <br />
hibernate在一个地方维护每个表的最后更新时间，其实也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配置里面。 <br />
当通过hibernate更新的时候，hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时间和这个缓存所查询的表，当hibernate查询一个缓存是否存在的时候，如果缓存存在，它还要取出缓存的生成时间和这个缓存所查询的表，然后去查找这些表的最后更新时间，如果有一个表在生成时间后更新过了，那么这个缓存是无效的。 <br />
可以看出，只要更新过一个表，那么凡是涉及到这个表的查询缓存就失效了，因此查询缓存的命中率可能会比较低。 <br />
<br />
<strong>Collection缓存</strong> <br />
需要在hbm的collection里面设置 <br />
&amp;lt;cache usage="read-write"/&amp;gt; <br />
假如class是Cat，collection叫children，那么ehcache里面配置 <br />
&amp;lt;cache name="com.xxx.pojo.Cat.children" <br />
&nbsp;&nbsp; maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" <br />
&nbsp;&nbsp; overflowToDisk="true" /&amp;gt; <br />
Collection的缓存和前面查询缓存的list一样，也是只保持一串id，但它不会因为这个表更新过就失效，一个collection缓存仅在这个collection里面的元素有增删时才失效。 <br />
这样有一个问题，如果你的collection是根据某个字段排序的，当其中一个元素更新了该字段时，导致顺序改变时，collection缓存里面的顺序没有做更新。 <br />
<br />
<strong>缓存策略</strong> <br />
只读缓存（read-only）：没有什么好说的 <br />
读/写缓存（read-write）:程序可能要的更新数据 <br />
不严格的读/写缓存（nonstrict-read-write）：需要更新数据，但是两个事务更新同一条记录的可能性很小，性能比读写缓存好 <br />
事务缓存（transactional）：缓存支持事务，发生异常的时候，缓存也能够回滚，只支持jta环境，这个我没有怎么研究过 <br />
<br />
读写缓存和不严格读写缓存在实现上的区别在于，读写缓存更新缓存的时候会把缓存里面的数据换成一个锁，其他事务如果去取相应的缓存数据，发现被锁住了，然后就直接取数据库查询。 <br />
在hibernate2.1的ehcache实现中，如果锁住部分缓存的事务发生了异常，那么缓存会一直被锁住，直到60秒后超时。 <br />
不严格读写缓存不锁定缓存中的数据。 <br />
<br />
<br />
<strong>使用二级缓存的前置条件</strong> <br />
你的hibernate程序对数据库有独占的写访问权，其他的进程更新了数据库，hibernate是不可能知道的。你操作数据库必需直接通过hibernate，如果你调用存储过程，或者自己使用jdbc更新数据库，hibernate也是不知道的。hibernate3.0的大批量更新和删除是不更新二级缓存的，但是据说3.1已经解决了这个问题。 <br />
这个限制相当的棘手，有时候hibernate做批量更新、删除很慢，但是你却不能自己写jdbc来优化，很郁闷吧。 <br />
SessionFactory也提供了移除缓存的方法，你一定要自己写一些JDBC的话，可以调用这些方法移除缓存，这些方法是： <br />
void evict(Class persistentClass) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Evict all entries from the second-level cache. <br />
void evict(Class persistentClass, Serializable id) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Evict an entry from the second-level cache. <br />
void evictCollection(String roleName) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Evict all entries from the second-level cache. <br />
void evictCollection(String roleName, Serializable id) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Evict an entry from the second-level cache. <br />
void evictQueries() <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Evict any query result sets cached in the default query cache region. <br />
void evictQueries(String cacheRegion) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Evict any query result sets cached in the named query cache region. <br />
不过我不建议这样做，因为这样很难维护。比如你现在用JDBC批量更新了某个表，有3个查询缓存会用到这个表，用evictQueries(String cacheRegion)移除了3个查询缓存，然后用evict(Class persistentClass)移除了class缓存，看上去好像完整了。不过哪天你添加了一个相关查询缓存，可能会忘记更新这里的移除代码。如果你的jdbc代码到处都是，在你添加一个查询缓存的时候，还知道其他什么地方也要做相应的改动吗？ <br />
<br />
---------------------------------------------------- <br />
<br />
<strong>总结：</strong> <br />
不要想当然的以为缓存一定能提高性能，仅仅在你能够驾驭它并且条件合适的情况下才是这样的。hibernate的二级缓存限制还是比较多的，不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下乱用，可能会有1+N的问题。不当的使用还可能导致读出脏数据。 <br />
如果受不了hibernate的诸多限制，那么还是自己在应用程序的层面上做缓存吧。 <br />
在越高的层面上做缓存，效果就会越好。就好像尽管磁盘有缓存，数据库还是要实现自己的缓存，尽管数据库有缓存，咱们的应用程序还是要做缓存。因为底层的缓存它并不知道高层要用这些数据干什么，只能做的比较通用，而高层可以有针对性的实现缓存，所以在更高的级别上做缓存，效果也要好些吧。 
<img src ="http://www.blogjava.net/zjrstar/aggbug/249857.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2009-01-05 10:40 <a href="http://www.blogjava.net/zjrstar/archive/2009/01/05/249857.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转贴]SSH2 - Struts2+Hibernate+Spring项目小结</title><link>http://www.blogjava.net/zjrstar/archive/2008/12/26/248440.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Fri, 26 Dec 2008 05:45:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/12/26/248440.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/248440.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/12/26/248440.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/248440.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/248440.html</trackback:ping><description><![CDATA[原文地址：http://www.wajava.com/bbs/viewthread_thread,51<br />
<br />
1、在web.xml中加载Spring的配置文件<br />
&lt;context-param&gt;<br />
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;<br />
&lt;param-value&gt;classpath*:spring/*.xml&lt;/param-value&gt;<br />
&lt;/context-param&gt;<br />
<br />
&lt;!--Spring ApplicationContext 载入 --&gt;<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;<br />
org.springframework.web.context.ContextLoaderListener<br />
&lt;/listener-class&gt;<br />
&lt;/listener&gt;<br />
<br />
<br />
2、配置属性文件<br />
&lt;!-- 属性文件读入 --&gt;<br />
&lt;bean id="propertyConfigurer"<br />
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;<br />
&lt;property name="locations"&gt;<br />
&lt;list&gt;<br />
&lt;value&gt;classpath*:config/ct-db-c3p0.properties&lt;/value&gt;<br />
&lt;value&gt;classpath*:config/mail.properties&lt;/value&gt;<br />
&lt;/list&gt;<br />
&lt;/property&gt;<br />
&lt;/bean&gt;<br />
<br />
3、配置数据源<br />
&lt;!-- 数据源定义,使用Apache c3p0 连接池 --&gt;<br />
&lt;bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"&gt;<br />
&lt;property name="driverClass" value="${....common.dbutils.c3p0.driver}" /&gt;<br />
&lt;property name="jdbcUrl" value="${....common.dbutils.c3p0.url}" /&gt;<br />
&lt;property name="user" value="${....common.dbutils.c3p0.user}" /&gt;<br />
&lt;property name="password" value="${....common.dbutils.c3p0.password}" /&gt;<br />
&lt;property name="maxStatementsPerConnection" value="${....common.dbutils.c3p0.maxStatementsPerConnection}"/&gt;<br />
&lt;property name="checkoutTimeout" value="${....common.dbutils.c3p0.checkoutTimeout}"/&gt;<br />
&lt;property name="initialPoolSize" value="${....common.dbutils.c3p0.initialPoolSize}"/&gt;<br />
&lt;property name="minPoolSize" value="${....common.dbutils.c3p0.minPoolSize}"/&gt;<br />
&lt;property name="maxPoolSize" value="${....common.dbutils.c3p0.maxPoolSize}"/&gt;<br />
&lt;property name="maxStatements" value="${....common.dbutils.c3p0.maxStatements}"/&gt;<br />
&lt;property name="acquireIncrement" value="${....common.dbutils.c3p0.acquireIncrement}"/&gt;<br />
&lt;property name="maxIdleTime" value="${....common.dbutils.c3p0.maxIdleTime}"/&gt;<br />
&lt;/bean&gt;<br />
<br />
&lt;!--Hibernate SessionFatory--&gt;<br />
&lt;bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"&gt;<br />
&lt;property name="dataSource" ref="dataSource"/&gt;<br />
&lt;property name="annotatedClasses"&gt;<br />
&lt;list&gt;<br />
&lt;!--添加bean --&gt;<br />
&lt;value&gt;....bean.AddressBook&lt;/value&gt;<br />
.......<br />
&lt;/list&gt;<br />
&lt;/property&gt;<br />
&lt;property name="hibernateProperties"&gt;<br />
&lt;props&gt;<br />
&lt;prop key="hibernate.dialect"&gt;org.hibernate.dialect.Oracle9Dialect&lt;/prop&gt;<br />
&lt;prop key="hibernate.show_sql"&gt;false&lt;/prop&gt;<br />
&lt;prop key="hibernate.generate_statistics"&gt;false&lt;/prop&gt;<br />
&lt;prop key="hibernate.connection.release_mode"&gt;auto&lt;/prop&gt;<br />
&lt;prop key="hibernate.autoReconnect"&gt;true&lt;/prop&gt;<br />
&lt;prop key="hibernate.cache.provider_class"&gt;org.hibernate.cache.EhCacheProvider&lt;/prop&gt;<br />
&lt;prop key="hibernate.cache.use_query_cache"&gt;true&lt;/prop&gt;<br />
&lt;/props&gt;<br />
&lt;/property&gt;<br />
&lt;/bean&gt;<br />
<br />
&lt;!--Hibernate TransactionManager--&gt;<br />
&lt;bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"&gt;<br />
&lt;property name="sessionFactory" ref="sessionFactory"/&gt;<br />
&lt;/bean&gt;<br />
<br />
<br />
4、依赖注入配置<br />
&lt;bean id="companyAction" class="....action.CompanyAction" scope="request"&gt;&lt;/bean&gt;<br />
&lt;bean name="companyBaseModel" class="....CompanyBaseModel"&gt;&lt;/bean&gt;<br />
&lt;bean class="....CompanyService" id="companyService"&gt;&lt;/bean&gt;<br />
&lt;bean class="....CompanyDAO" id="companyDAO"&gt;&lt;/bean&gt;<br />
注：对beans的设置<br />
&lt;beans default-autowire="byName" default-lazy-init="true"&gt;...&lt;/beans&gt;<br />
<br />
<br />
<br />
5、Spring怎样注入Class&lt;T&gt;（泛型类型对象）？<br />
在事务配置时，将proxy-target-class设置为false即可。不能为true，因为要针对接口代理。<br />
如：&lt;aop:config proxy-target-class="false"&gt;<br />
<br />
6、Spring中采用构造方法注入注意要点：<br />
在配置文件中显式书写注入的参数。如：<br />
&lt;bean class="....impl.JobService"<br />
id="retJobService"&gt;<br />
&lt;constructor-arg ref="retJobDao" /&gt;<br />
&lt;/bean&gt;<br />
多个参数的构造函数示例<br />
&lt;bean class="....impl.TypeService"<br />
id="typeService"&gt;<br />
&lt;constructor-arg index="0" ref="typeDAO" /&gt;<br />
&lt;constructor-arg index="1" type="boolean"&gt;<br />
&lt;value&gt;false&lt;/value&gt;<br />
&lt;/constructor-arg&gt;<br />
&lt;/bean&gt;<br />
<br />
<br />
7、Spring 2.0 结合AspectJ pointcut语法配置AOP详解<br />
Spring参考文档 7.3 chema-based AOP support 提供了aspect,advisor,advide三种组装方法的解释，其中aspect是aspectJ原装，但稍复杂，<br />
&lt;aop:config proxy-target-class="true"&gt;<br />
&lt;aop:advisor pointcut="execution(* *..BookManager.save(..))||execution(* *..BookManager.remove(..))" advice-ref="lowStockBookFlushingAdvice"/&gt;<br />
&lt;aop:advisor pointcut="execution(* *..BookStockChecker.getLowStockBooks())" advice-ref="lowStockBookCachingAdvice"/&gt;<br />
&lt;/aop:config&gt;<br />
以上几句定义使用cglib创建Proxy, 为BookManager的save()和remove()加上lowStockBookFlushingAdvice，为 BookStockChecker.getLowStockBooks加上lowStockBookCachingAdvice.<br />
<br />
execution(* *..BookManager.save(..))<br />
第一颗* 代表ret-type-pattern 返回值可任意，<br />
*..BookManager 代表任意Pacakge里的BookManager类。<br />
如果写成com.xyz.service.* 则代表com.xyz.service下的任意类<br />
com.xyz.service..* com.xyz.service则代表com.xyz.service及其子package下的任意类<br />
save代表save方法，也可以写save* 代表saveBook()等方法<br />
(..) 匹配0个参数或者多个参数的，任意类型<br />
(x,..) 第一个参数的类型必须是X<br />
(x,*,*,s,..) 匹配至少4个参数，第一个参数必须是x类型，第二个和第三个参数可以任意，第四个必须是s类型。<br />
<br />
8、事务配置的不同形式<br />
事务配置一：<br />
&lt;!-- 支持 @AspectJ 标记--&gt;<br />
&lt;aop:aspectj-autoproxy /&gt;<br />
<br />
&lt;!-- 以AspectJ方式 定义 AOP --&gt;<br />
&lt;aop:config proxy-target-class="false"&gt;<br />
&lt;aop:advisor<br />
pointcut="execution(* ....recruitment.service.impl..*.*(..)) || execution(* ....employeeinfo.service.impl..*Service.*(..))"<br />
advice-ref="txAdvice" /&gt;<br />
&lt;/aop:config&gt;<br />
<br />
&lt;!-- 基本事务定义,使用transactionManager作事务管理,默认get*方法的事务为readonly,其余方法按默认设置.<br />
默认的设置请参考Spring文档事务一章. --&gt;<br />
&lt;tx:advice id="txAdvice" transaction-manager="transactionManager"&gt;<br />
&lt;tx:attributes&gt;<br />
&lt;tx:method name="get*" read-only="true" propagation="REQUIRED" /&gt;<br />
&lt;tx:method name="load*" read-only="true" propagation="REQUIRED" /&gt;<br />
&lt;tx:method name="find*" read-only="true" propagation="REQUIRED" /&gt;<br />
&lt;tx:method name="*" propagation="REQUIRED" /&gt;<br />
&lt;/tx:attributes&gt;<br />
&lt;/tx:advice&gt;<br />
<br />
<br />
事务配置二：<br />
&lt;!-- 支持 @AspectJ 标记--&gt;<br />
&lt;aop:aspectj-autoproxy /&gt;<br />
<br />
&lt;!-- 以AspectJ方式 定义 AOP --&gt;<br />
&lt;aop:config proxy-target-class="false"&gt;<br />
&lt;aop:advisor<br />
pointcut="execution(* ....employeeinfo.service.impl..*Service.*(..))"<br />
advice-ref="txAdvice" /&gt;<br />
<br />
&lt;aop:advisor<br />
pointcut="execution(* ....recruitment.service.impl..*.*(..)) "<br />
advice-ref="txAdviceRet" /&gt;<br />
&lt;/aop:config&gt;<br />
<br />
&lt;!-- 基本事务定义,使用transactionManager作事务管理,默认get*方法的事务为readonly,其余方法按默认设置.<br />
默认的设置请参考Spring文档事务一章. --&gt;<br />
&lt;tx:advice id="txAdvice" transaction-manager="transactionManager"&gt;<br />
&lt;tx:attributes&gt;<br />
......<br />
&lt;/tx:attributes&gt;<br />
&lt;/tx:advice&gt;<br />
&lt;tx:advice id="txAdviceRet"<br />
transaction-manager="transactionManager"&gt;<br />
&lt;tx:attributes&gt;<br />
.........<br />
&lt;/tx:attributes&gt;<br />
&lt;/tx:advice&gt;<br />
<br />
事务配置三：（在java文件中配置）<br />
需要单独配置事务的类名前配置事务开启<br />
@Transactional(propagation = Propagation.SUPPORTS)<br />
需要使用事务的方法前配置开启事务的信息<br />
@Transactional(propagation = Propagation.REQUIRED)<br />
如：<br />
@Transactional(propagation = Propagation.SUPPORTS)<br />
public class ApplierService extends BaseService&lt;Applier&gt; implements<br />
IApplierService {<br />
@Transactional(propagation = Propagation.REQUIRED)<br />
public void addOrModify(Applier t) {<br />
applierDao.saveOrUpdate(toDBValue(t));<br />
}<br />
}<br />
<br />
9、正确配置重写父类方法时事务<br />
参阅：<a href="http://aumy2008.javaeye.com/admin/blogs/152928" target="_blank">http://aumy2008.javaeye.com/admin/blogs/152928</a><br />
<br />
10、spring中bean的作用域详解<br />
bean属性scope的选取（prototype、request、session、global session）：<br />
&lt;bean name="companyAction"<br />
class="....CompanyAction" scope="prototype"/&gt;<br />
s:datetimepicker录入框提交正常。<br />
prototype作用域部署的bean，每一次请求（将其注入到另一个bean中，或者以程序的方式调用容器的getBean()方法）<br />
都会产生一个新的bean实例，相当一个new的操作，对于prototype作用域的bean，有一点非常重要，<br />
那就是Spring不能对一个prototype bean的整个生命周期负责，<br />
容器在初始化、配置、装饰或者是装配完一个prototype实例后，将它交给客户端，<br />
随后就对该prototype实例不闻不问了。不管何种作用域，容器都会调用所有对象的初始化生命周期回调方法，<br />
而对prototype而言，任何配置好的析构生命周期回调方法都将不会被调用。<br />
清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源，都是客户端代码的职责。<br />
（让Spring容器释放被singleton作用域bean占用资源的一种可行方式是，通过使用bean的后置处理器，<br />
该处理器持有要被清除的bean的引用。）<br />
<br />
request、session、global session使用的时候首先要在web.xml中做如下配置：<br />
如果你使用的是Servlet 2.4及以上的web容器，那么你仅需要在web应用的XML声明文件web.xml中增加下述ContextListener即可：<br />
&lt;listener&gt;<br />
&lt;listener-class&gt;org.springframework.web.context.request.RequestContextListener&lt;/listener-class&gt;<br />
&lt;/listener&gt;<br />
<br />
&lt;bean name="companyAction"<br />
class="....action.CompanyAction" scope="request"/&gt;<br />
s:datetimepicker录入框提交正常。<br />
<br />
&lt;bean name="companyAction"<br />
class="....action.CompanyAction" scope="session"/&gt;<br />
s:datetimepicker录入框不能正常提交。<br />
<br />
&lt;bean name="companyAction"<br />
class="....action.CompanyAction" scope="global session"/&gt;<br />
java.lang.IllegalStateException: No Scope registered for scope 'global session'<br />
分析：global session作用域类似于标准的HTTP Session作用域，不过它仅仅在基于portlet的web应用中才有意义。<br />
<br />
Spring中bean的作用域相关网站：<br />
<a href="http://doc.javanb.com/spring-framework-reference-zh-2-0-5/ch03s04.html" target="_blank">http://doc.javanb.com/spring-framework-reference-zh-2-0-5/ch03s04.html</a><br />
<img src ="http://www.blogjava.net/zjrstar/aggbug/248440.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-12-26 13:45 <a href="http://www.blogjava.net/zjrstar/archive/2008/12/26/248440.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转贴]Hibernate 的jar包</title><link>http://www.blogjava.net/zjrstar/archive/2008/12/24/248067.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Wed, 24 Dec 2008 06:30:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/12/24/248067.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/248067.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/12/24/248067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/248067.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/248067.html</trackback:ping><description><![CDATA[原文地址：<a href="http://www.ilina.cn/cto/p278/J27834217.shtml">http://www.ilina.cn/cto/p278/J27834217.shtml</a><br />
<br />
<p class="g_w_100 g_t_wrap g_t_center g_t_bold g_t_24 g_c_pdin c07" id="blogtitle_fks_085066084094083074086082085095085081088071083082083070">Hibernate 的jar包说明（转）<br />
</p>
<p style="text-indent: 2em">Hibernate一共包括了23个jar包，令人眼花缭乱。下载Hibernate，例如2.0.3稳定版本，解压缩，可以看到一个hibernate2.jar和lib目录下有22个jar包： </p>
<p style="text-indent: 2em">（1）hibernate2.jar: </p>
<p style="text-indent: 2em">　　Hibernate的库，没有什么可说的，必须使用的jar包 </p>
<p style="text-indent: 2em">（2）cglib-asm.jar: </p>
<p style="text-indent: 2em">　　CGLIB库，Hibernate用它来实现PO字节码的动态生成，非常核心的库，必须使用的jar包 </p>
<p style="text-indent: 2em">（3）dom4j.jar: </p>
<p style="text-indent: 2em">　　dom4j是一个Java的XML API，类似于jdom，用来读写XML文件的。dom4j是一个非常非常优秀的Java XML API，具有性能优异、功能强大和极端易用使用的特点，同时它也是一个开放源代码的软件，可以在SourceForge上找到它。在IBM developerWorks上面可以找到一篇文章，对主流的Java XML API进行的性能、功能和易用性的评测，dom4j无论在那个方面都是非常出色的。我早在将近两年之前就开始使用dom4j，直到现在。如今你可以看到越来越多的Java软件都在使用dom4j来读写XML，特别值得一提的是连Sun的JAXM也在用dom4j。这是必须使用的jar包，Hibernate用它来读写配置文件。 </p>
<p style="text-indent: 2em">（4）odmg.jar: </p>
<p style="text-indent: 2em">　　ODMG是一个ORM的规范，Hibernate实现了ODMG规范，这是一个核心的库，必须使用的jar包。 </p>
<p style="text-indent: 2em">（5）commons-collections.jar： </p>
<p style="text-indent: 2em">　　Apache Commons包中的一个，包含了一些Apache开发的集合类，功能比java.util.*强大。必须使用的jar包。 </p>
<p style="text-indent: 2em">（6）commons-beanutils.jar： </p>
<p style="text-indent: 2em">　　Apache Commons包中的一个，包含了一些Bean工具类类。必须使用的jar包。 </p>
<p style="text-indent: 2em">（7）commons-lang.jar: </p>
<p style="text-indent: 2em">　　Apache Commons包中的一个，包含了一些数据类型工具类，是java.lang.*的扩展。必须使用的jar包。 </p>
<p style="text-indent: 2em">（8）commons-logging.jar: </p>
<p style="text-indent: 2em">　　Apache Commons包中的一个，包含了日志功能，必须使用的jar包。这个包本身包含了一个Simple Logger，但是功能很弱。在运行的时候它会先在CLASSPATH找log4j，如果有，就使用log4j，如果没有，就找JDK1.4带的java.util.logging，如果也找不到就用Simple Logger。commons-logging.jar的出现是一个历史的的遗留的遗憾，当初Apache极力游说Sun把log4j加入JDK1.4，然而JDK1.4项目小组已经接近发布JDK1.4产品的时间了，因此拒绝了Apache的要求，使用自己的java.util.logging，这个包的功能比log4j差的很远，性能也一般。</p>
<p style="text-indent: 2em">　　后来Apache就开发出来了commons-logging.jar用来兼容两个logger。因此用commons-logging.jar写的log程序，底层的Logger是可以切换的，你可以选择log4j，java.util.logging或者它自带的Simple Logger。不过我仍然强烈建议使用log4j，因为log4j性能很高，log输出信息时间几乎等于System.out，而处理一条log平均只需要5us。你可以在Hibernate的src目录下找到Hibernate已经为你准备好了的log4j的配置文件，你只需要到Apache 网站去下载log4j就可以了。commons-logging.jar也是必须的jar包。 </p>
<p style="text-indent: 2em">使用Hibernate必须的jar包就是以上的这几个，剩下的都是可选的。 </p>
<p style="text-indent: 2em">　　ant.jar: </p>
<p style="text-indent: 2em">　　Ant编译工具的jar包，用来编译Hibernate源代码的。如果你不准备修改和编译Hibernate源代码，那么就没有什么用，可选的jar包 </p>
<p style="text-indent: 2em">　　optional.jar： </p>
<p style="text-indent: 2em">　　Ant的一个辅助包。 </p>
<p style="text-indent: 2em">　　c3p0.jar： </p>
<p style="text-indent: 2em">　　C3PO是一个数据库连接池，Hibernate可以配置为使用C3PO连接池。如果你准备用这个连接池，就需要这个jar包。 </p>
<p style="text-indent: 2em">　　proxool.jar： </p>
<p style="text-indent: 2em">　　也是一个连接池，同上。 </p>
<p style="text-indent: 2em">　　commons-pool.jar, commons-dbcp.jar: </p>
<p style="text-indent: 2em">　　DBCP数据库连接池，Apache的Jakarta组织开发的，Tomcat4的连接池也是DBCP。 </p>
<p style="text-indent: 2em">　　实际上Hibernate自己也实现了一个非常非常简单的数据库连接池，加上上面3个，你实际上可以在Hibernate上选择4种不同的数据库连接池，选择哪一个看个人的偏好，不过DBCP可能更通用一些。另外强调一点，如果在EJB中使用Hibernate，一定要用App Server的连接池，不要用以上4种连接池，否则容器管理事务不起作用。 </p>
<p style="text-indent: 2em">　　connector.jar: </p>
<p style="text-indent: 2em">　　JCA 规范，如果你在App Server上把Hibernate配置为Connector的话，就需要这个jar。不过实际上一般App Server肯定会带上这个包，所以实际上是多余的包。 </p>
<p style="text-indent: 2em">　　jaas.jar: </p>
<p style="text-indent: 2em">　　JAAS是用来进行权限验证的，已经包含在JDK1.4里面了。所以实际上是多余的包。 </p>
<p style="text-indent: 2em">　　jcs.jar： </p>
<p style="text-indent: 2em">　　如果你准备在Hibernate中使用JCS的话，那么必须包括它，否则就不用。 </p>
<p style="text-indent: 2em">　　jdbc2_0-stdext.jar: </p>
<p style="text-indent: 2em">　　JDBC2.0的扩展包，一般来说数据库连接池会用上它。不过App Server都会带上，所以也是多余的。 </p>
<p style="text-indent: 2em">　　jta.jar： </p>
<p style="text-indent: 2em">　　JTA规范，当Hibernate使用JTA的时候需要，不过App Server都会带上，所以也是多余的。 </p>
<p style="text-indent: 2em">　　junit.jar: </p>
<p style="text-indent: 2em">　　Junit包，当你运行Hibernate自带的测试代码的时候需要，否则就不用。 </p>
<p style="text-indent: 2em">　　xalan.jar, xerces.jar, xml-apis.jar: </p>
<p style="text-indent: 2em">　　Xerces是XML解析器，Xalan是格式化器，xml-apis实际上是JAXP。一般App Server都会带上，JDK1.4也包含了解析器，不过不是Xerces，是Crimson，效率比较差，不过Hibernate用XML只不过是读取配置文件，性能没什么紧要的，所以也是多余的。</p>
<p style="text-indent: 2em">
<table>
    <tbody>
        <tr>
            <td>
            <p>&nbsp;</p>
            <p style="text-indent: 2em"><a href="http://ant.apache.org/">ant-1.63.jar</a></p>
            <p style="text-indent: 2em">http://ant.apache.org/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">Ant 的核心包,在构建Hibernate 时会用到</p>
            <p style="text-indent: 2em"><a href="http://www.antlr.org/">antlr-2.7.5H3.jar</a></p>
            <p style="text-indent: 2em">http://www.antlr.org/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">语言转换工,Hibernate利用它实现 HQL 到 SQL的转换</p>
            <p style="text-indent: 2em"><a href="http://asm.objectweb.org/">asm.jar/asm-attrs.jar </a></p>
            <p style="text-indent: 2em">http://asm.objectweb.org/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">ASM 字节转换库</p>
            <p style="text-indent: 2em"><a href="http://sourceforge.net/projects/c3p0">c3p0-0.8.5.2.jar</a></p>
            <p style="text-indent: 2em">http://sourceforge.net/projects/c3p0&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">C3PO JDBC 连接池工具</p>
            <p style="text-indent: 2em"><a href="http://cglib.sourceforge.net/">cglib-2.1.jar</a></p>
            <p style="text-indent: 2em">http://cglib.sourceforge.net/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">高效的代码生成工具, Hibernate用它在运行时扩展 Java类和实现 Java 接口</p>
            <p style="text-indent: 2em"><a href="http://jakarta.apache.org/commons/collections">commons-collections-2.1.1.jar</a></p>
            <p style="text-indent: 2em">http://jakarta.apache.org/commons/collections</p>
            <p style="text-indent: 2em">Apache 的工具集,用来增强Java对集合的处理能力</p>
            <p style="text-indent: 2em"></p>
            <p style="text-indent: 2em"><a href="http://jakarta.apache.org/commons/logging/">commons-logging-1.0.4.jar</a></p>
            <p style="text-indent: 2em">http://jakarta.apache.org/commons/logging/&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">Apache 软件基我组所提供的日志工具</p>
            <p style="text-indent: 2em"></p>
            <p style="text-indent: 2em"><a href="http://gee.cs.oswego.edu/dl/classes%20/EDU/oswego/cs/dl/util/concurrent/intro.html">concurrent-1.3.2.jar</a></p>
            <p style="text-indent: 2em">http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;</p>
            <p style="text-indent: 2em">线程同步工具,在使用JBoss 的树状缓存时需要用到</p>
            <p style="text-indent: 2em"><a href="http://java.sun.com/j2ee/connector/">connector.jar</a></p>
            <p style="text-indent: 2em">http://java.sun.com/j2ee/connector/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">用连接多个应用服务器的标准连接器</p>
            <p style="text-indent: 2em"><a href="http://dom4.j.org/">dom4j-1.6.jar</a></p>
            <p style="text-indent: 2em">http://dom4.j.org/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">dom4j XML 解析器</p>
            <p style="text-indent: 2em"><a href="http://sourceforge.net/projects/echache">ehcache-1.1.jar</a></p>
            <p style="text-indent: 2em">http://sourceforge.net/projects/echache&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">缓存工具.在没有提供其他缓存工具时,这个缓存工具是必不可少的</p>
            <p style="text-indent: 2em"><a href="http://java.sun.com/products/jass/">jaas.jar</a></p>
            <p style="text-indent: 2em">http://java.sun.com/products/jass/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</p>
            <p style="text-indent: 2em">标准的 Java 权限和认证服务包</p>
            <p style="text-indent: 2em"><a href="http://hi.baidu.com/lanren_/blog/item/jaxen.org/">jaxen-1.1-beta-4.jar</a></p>
            <p style="text-indent: 2em">http:jaxen.org/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">通用的 XPath 处理引擎</p>
            <p style="text-indent: 2em"><a href="http://www.jboss.com/products/jbosscache">jboss-cache.jar</a></p>
            <p style="text-indent: 2em">http://www.jboss.com/products/jbosscache&nbsp;&nbsp; &nbsp;&nbsp;</p>
            <p style="text-indent: 2em">JBoss 的一种树状缓存实现工具</p>
            <p style="text-indent: 2em"><a href="http://jboss.org/">jboss-common.jar</a></p>
            <p style="text-indent: 2em">http://jboss.org/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">Jboss 的基础包,在使用 JBoss 的树状缓存时必须有此包</p>
            <p style="text-indent: 2em"><a href="http://jboss.org/">jboss-jmx.jar</a></p>
            <p style="text-indent: 2em">http://jboss.org/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">JBoss 的 JMX 实现包</p>
            <p style="text-indent: 2em"><a href="http://jboss.org/">jboss-system.jar</a></p>
            <p style="text-indent: 2em">http://jboss.org/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">JBoss 的核心,包括服务器和部署引擎</p>
            <p style="text-indent: 2em"><a href="http://java.sun.com/products/jdbc/download.html#spec">jdbc2_0-stdext.jar</a></p>
            <p style="text-indent: 2em">http://java.sun.com/products/jdbc/download.html#spec&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">标准的 JDBC 2.0 扩展API</p>
            <p style="text-indent: 2em"><a href="http://www.jgroups.org/">jgroups2.2.7.jar</a></p>
            <p style="text-indent: 2em">http://www.jgroups.org/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">网络通信工具包</p>
            <p style="text-indent: 2em"><a href="http://java.sun.com/products/jta">jta.jar</a></p>
            <p style="text-indent: 2em">http://java.sun.com/products/jta&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</p>
            <p style="text-indent: 2em">标准的 JAVA 事务处理接口</p>
            <p style="text-indent: 2em"><a href="http://www.junit.org/">junit-3.8.1.jar</a></p>
            <p style="text-indent: 2em">http://www.junit.org/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">JUnit 测试框架</p>
            <p style="text-indent: 2em"><a href="http://logging.apache.org/log4j/">log4.j-1.2.9.jar</a></p>
            <p style="text-indent: 2em">http://logging.apache.org/log4j/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">log4j 库,Apache 的日志工具</p>
            <p style="text-indent: 2em"><a href="http://www.opensymphony.com/oscache/">oscache-2.1.jar</a></p>
            <p style="text-indent: 2em">http://www.opensymphony.com/oscache/ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">Java 对象的缓存工具</p>
            <p style="text-indent: 2em"><a href="http://proxool.sourceforge.net/">proxool-0.8.3.jar</a></p>
            <p style="text-indent: 2em">http://proxool.sourceforge.net/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">Proxool JDBC 连接池工具</p>
            <p style="text-indent: 2em"><a href="http://swarmcache.sourceforge.net/">swarmcache-1.0rc2.jar</a></p>
            <p style="text-indent: 2em">http://swarmcache.sourceforge.net/&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">Hibernate 可以使用的一种缓存工具</p>
            <p style="text-indent: 2em">versioncheck.jar </p>
            <p style="text-indent: 2em">版本检查工具包,用于在构建Hibernate 的时候检查辅助 jar 包文件的版本</p>
            <p style="text-indent: 2em"><a href="http://xml.apache.org/xerces2-j/">xerces-2.6.2.jar</a></p>
            <p style="text-indent: 2em">http://xml.apache.org/xerces2-j/&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;</p>
            <p style="text-indent: 2em">SAX XML 解析器</p>
            <p style="text-indent: 2em"><a href="http://xml.apache.org/xerces2-j/">xml-apis.jar</a></p>
            <p style="text-indent: 2em">http://xml.apache.org/xerces2-j/&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</p>
            <p style="text-indent: 2em">Java语言中标准的XML 解析器</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p class="g_w_100 g_t_wrap g_t_center g_t_bold g_t_24 g_c_pdin c07" id="blogtitle_fks_085066084094083074086082085095085081088071083082083070"><br />
<br />
&nbsp;</p>
<img src ="http://www.blogjava.net/zjrstar/aggbug/248067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-12-24 14:30 <a href="http://www.blogjava.net/zjrstar/archive/2008/12/24/248067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转贴]Struts相关jar包</title><link>http://www.blogjava.net/zjrstar/archive/2008/12/24/248065.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Wed, 24 Dec 2008 06:27:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/12/24/248065.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/248065.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/12/24/248065.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/248065.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/248065.html</trackback:ping><description><![CDATA[原文地址：http://blog.163.com/panyonglong_917/blog/static/179474552008728112039503/<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Struts相关jar包简介&nbsp; <br />
<br />
<strong>commons-beanutils.jar</strong>
<div>Commons-Beanutils 这个是jakarta commons项目中的一个子项目。这个项目开发的目的是帮助开发者动态的获取/设值Java Bean的属性，同时解决每次都要写getXXX和setXXX的麻烦。 </div>
<div><strong>commons-digester.jar</strong> </div>
<div>Digester本来仅仅是Jakarta Struts中的一个工具，用于处理struts-config.xml配置文件。显然，将XML文件转换成相应的Java对象是一项很通用的功能，这个工具理应具有更广泛的用途，所以很快它就在Jakarta Commons项目(用于提供可重用的Java组件库)中有了一席之地。 </div>
<div>在内部， Struts 使用来自于Jakarta Commons[ASF, Commons] 项目的Digester 来解析Struts配置文件。Digester 使用struts-config DTD 来校验文档的格式，并且创建文档所描述的Java对象。如果XML文件包含了非正式文档化的元素，或者以非正式文档化的方式使用了元素，Digester 将不会处理这个文件。 </div>
<div><strong>commons-fileupload.jar</strong> </div>
<div>Commons-FileUpload FileUpload 使得在你可以在应用和Servlet中容易的加入强大和高性能的文件上传能力struts中上传文件要用到。</div>
<div>struts的验证框架依赖以下的两个包：</div>
<div><strong>&nbsp;commons-validator.jar</strong> </div>
<div>(校验方法)和校验规则。支持校验规则的和错误消息的国际化。 struts使用它对表单进行验证。 </div>
<div><strong>&nbsp;&nbsp; &nbsp;jakarta-oro.jar</strong> </div>
<div>Commons-EL Commons-Jexl Search Jakarta ORO Jakarta ORO一套文本处理工具,能提供perl5.0兼容的正则表达式,AWK-like正则表达式, glob表达式。还提供替换,分割,文件名过虑等功能。</div>
<div><strong>struts.jar</strong></div>
<div>struts核心包。</div>
<div>其他的一下jar包</div>
<div><strong>commons-collections.jar</strong></div>
<div>扩展了标准的Java Collection框架，提供了额外的Map、List 和Set实现以及多个有用的工具类库。功能比java.util.*强大。</div>
<div><strong>commons-logging.jar:</strong> </div>
<div>Apache Commons包中的一个，包含了日志功能。这个包本身包含了一个Simple Logger，但是功能很弱。在运行的时候它会先在CLASSPATH找log4j，如果有，就使用log4j，如果没有，就找JDK1.4带的 java.util.logging，如果也找不到就用Simple Logger。commons-logging.jar的出现是一个历史的的遗留的遗憾，当初Apache极力游说Sun把log4j加入JDK1.4，然而JDK1.4项目小组已经接近发布JDK1.4产品的时间了，因此拒绝了Apache的要求，使用自己的java.util.logging，这个包的功能比log4j差的很远，性能也一般。</div>
<div>后来Apache就开发出来了commons-logging.jar用来兼容两个 logger。因此用commons-logging.jar写的log程序，底层的Logger是可以切换的，你可以选择 log4j，java.util.logging或者它自带的Simple Logger。不过我仍然强烈建议使用log4j，因为log4j性能很高，log输出信息时间几乎等于System.out，而处理一条log平均只需要5us。你可以在Hibernate的src目录下找到Hibernate已经为你准备好了的log4j的配置文件，你只需要到Apache 网站去下载log4j就可以了。commons-logging.jar也是必须的jar包。</div>
<img src ="http://www.blogjava.net/zjrstar/aggbug/248065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-12-24 14:27 <a href="http://www.blogjava.net/zjrstar/archive/2008/12/24/248065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转贴]spring jar 包详解</title><link>http://www.blogjava.net/zjrstar/archive/2008/12/24/248064.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Wed, 24 Dec 2008 06:22:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/12/24/248064.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/248064.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/12/24/248064.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/248064.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/248064.html</trackback:ping><description><![CDATA[原文位置：http://blog.163.com/panyonglong_917/blog/static/179474552008728112259392/<br />
<br />
<p class="g_w_100 g_t_wrap g_t_center g_t_bold g_t_24 g_c_pdin c07" id="blogtitle_fks_085066084095084066081087086095085081088071083082083070">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spring jar 包详解<br />
spring.jar是包含有完整发布的单个jar包，spring.jar中包含除了 spring-mock.jar里所包含的内容外其它所有jar包的内容，因为只有在开发环境下才会用到spring-mock.jar来进行辅助测试，正式应用系统中是用不得这些类的。　　除了spring.jar文件，Spring还包括有其它13个独立的jar包，各自包含着对应的Spring组件，用户可以根据自己的需要来选择组合自己的jar包，而不必引入整个spring.jar的所有类文件。<br />
&nbsp;(1) spring-core.jar 这个jar文件包含Spring框架基本的核心工具类，Spring其它组件要都要使用到这个包里的类，是其它组件的基本核心，当然你也可以在自己的应用系统中使用这些工具类。<br />
&nbsp;(2) spring-beans.jar 这个jar文件是所有应用都要用到的，它包含访问配置文件、创建和管理bean以及进行Inversion of Control / Dependency Injection（IoC/DI）操作相关的所有类。如果应用只需基本的IoC/DI支持，引入spring-core.jar及spring- beans.jar文件就可以了。 <br />
(3) spring-aop.jar 这个jar文件包含在应用中使用Spring的AOP特性时所需的类。使用基于AOP的Spring特性，如声明型事务管理（Declarative Transaction Management），也要在应用里包含这个jar包。<br />
&nbsp;(4) spring-context.jar 　　这个jar文件为Spring核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类，JDNI所需的全部类，UI方面的用来与模板（Templating）引擎如 Velocity、FreeMarker、JasperReports集成的类，以及校验Validation方面的相关类。 <br />
(5) spring-dao.jar 　　这个jar文件包含Spring DAO、Spring Transaction进行数据访问的所有类。为了使用声明型事务支持，还需在自己的应用里包含spring-aop.jar。 <br />
(6) spring-hibernate.jar 　　这个jar文件包含Spring对Hibernate 2及Hibernate 3进行封装的所有类。 <br />
(7) spring-jdbc.jar 　　这个jar文件包含对Spring对JDBC数据访问进行封装的所有类。<br />
&nbsp;(8) spring-orm.jar 　　这个jar文件包含Spring对DAO特性集进行了扩展，使其支持 iBATIS、JDO、OJB、TopLink，因为Hibernate已经独立成包了，现在不包含在这个包里了。这个jar文件里大部分的类都要依赖 spring-dao.jar里的类，用这个包时你需要同时包含spring-dao.jar包。<br />
&nbsp;(9) spring-remoting.jar 　　这个jar文件包含支持EJB、JMS、远程调用Remoting（RMI、Hessian、Burlap、Http Invoker、JAX-RPC）方面的类。 <br />
(10) spring-support.jar 　　这个jar文件包含支持缓存Cache（ehcache）、JCA、JMX、邮件服务（Java Mail、COS Mail）、任务计划Scheduling（Timer、Quartz）方面的类。<br />
&nbsp;(11) spring-web.jar 　　这个jar文件包含Web应用开发时，用到Spring框架时所需的核心类，包括自动载入WebApplicationContext特性的类、 Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。<br />
&nbsp;(12) spring-webmvc.jar 　　这个jar文件包含Spring MVC框架相关的所有类。包含国际化、标签、Theme、视图展现的FreeMarker、JasperReports、Tiles、Velocity、 XSLT相关类。当然，如果你的应用使用了独立的MVC框架，则无需这个JAR文件里的任何类。 <br />
(13) spring-mock.jar 　　这个jar文件包含Spring一整套mock类来辅助应用的测试。Spring测试套件使用了其中大量mock类，这样测试就更加简单。模拟 HttpServletRequest和HttpServletResponse类在Web应用单元测试是很方便的。　　<br />
如何选择这些发布包，决定选用哪些发布包其实相当简单。如果你正在构建Web应用并将全程使用Spring，那么最好就使用单个全部的 spring.jar文件；如果你的应用仅仅用到简单的Inversion of Control / Dependency Injection（IoC/DI）容器，那么只需spring-core.jar与spring-beans.jar即可；如果你对发布的大小要求很高，那么就得精挑细选了，只取包含自己所需特性的jar文件了。采用独立的发布包你可以避免包含自己的应用不需要的全部类。当然你可以采用其它的一些工具来设法令整个应用包变小，节省空间的重点在于准确地找出自己所需的Spring依赖类，然后合并所需的类与包就可以了。Eclispe有个插件叫 ClassPath Helper可以帮你找找所依赖的类。 <br />
<br />
Spring包依赖说明: <br />
1) spring-core.jar需commons-collections.jar，spring-core.jar是以下其它各个的基本。<br />
&nbsp;2) spring-beans.jar需spring-core.jar，cglib-nodep-2.1_3.jar <br />
3) spring-aop.jar需spring-core.jar，spring-beans.jar，cglib-nodep- 2.1_3.jar，aopalliance.jar <br />
4) spring-context.jar需spring-core.jar，spring-beans.jar，spring- aop.jar，commons-collections.jar，aopalliance.jar <br />
5) spring-dao.jar需spring-core.jar，spring-beans.jar，spring-aop.jar，spring- context.jar <br />
6) spring-jdbc.jar需spring-core.jar，spring-beans.jar，spring-dao.jar <br />
7) spring-web.jar需spring-core.jar，spring-beans.jar，spring-context.jar <br />
8) spring-webmvc.jar需spring-core.jar/spring-beans.jar/spring-context.jar /spring-web.jar <br />
9) spring -hibernate.jar需spring-core.jar，spring-beans.jar，spring-aop.jar，spring- dao.jar，spring-jdbc.jar，spring-orm.jar，spring-web.jar，spring-webmvc.jar <br />
10) spring-orm.jar需spring-core.jar，spring-beans.jar，spring-aop.jar，spring- dao.jar，spring-jdbc.jar，spring-web.jar，spring-webmvc.jar <br />
11) spring -remoting.jar需spring-core.jar，spring-beans.jar，spring-aop.jar，spring- dao.jar，spring-context.jar，spring-web.jar，spring-webmvc.jar <br />
12) spring-support.jar需spring-core.jar，spring-beans.jar，spring- aop.jar，spring-dao.jar，spring-context.jar，spring-jdbc.jar <br />
13) spring-mock.jar需spring-core.jar，spring-beans.jar，spring-dao.jar，spring- context.jar，spring-jdbc.jar <br />
</p>
<img src ="http://www.blogjava.net/zjrstar/aggbug/248064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-12-24 14:22 <a href="http://www.blogjava.net/zjrstar/archive/2008/12/24/248064.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转贴]Spring JTA应用之Atomikos配置 </title><link>http://www.blogjava.net/zjrstar/archive/2008/12/23/247924.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Tue, 23 Dec 2008 07:47:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/12/23/247924.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/247924.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/12/23/247924.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/247924.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/247924.html</trackback:ping><description><![CDATA[原文地址：<a href="http://tom-duan.javaeye.com/blog/147599">http://tom-duan.javaeye.com/blog/147599</a><br />
<br />
Atomikos,是一个基于Java的开源事务管理器，提供了事务管理和连接池，不需要应用服务器支持，支持JDBC和JMS事务，能提供对Spring，Hibernate的集成，有兴趣多了解的可以直接参考说明文当，有详细的介绍和使用说明。 <br />
<br />
Atomikos可以到http://www.atomikos.com/products.html#ate下载,最新版本是3.2.0 <br />
<br />
首先,仍然是一个相关的配置文件，用来设置相关的环境,打开解压缩后Atomikos根目录,拷贝jta.properties到classpath中，并修改为如下内容 <br />
jta.properties <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147599#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory &nbsp;&nbsp;</span></span></li>
    <li><span>com.atomikos.icatch.console_file_name&nbsp;=&nbsp;tm.out &nbsp;&nbsp;</span></li>
    <li><span>com.atomikos.icatch.log_base_name&nbsp;=&nbsp;tmlog &nbsp;&nbsp;</span></li>
    <li><span>com.atomikos.icatch.tm_unique_name&nbsp;=&nbsp;com.atomikos.spring.jdbc.tm &nbsp;&nbsp;</span></li>
    <li><span>com.atomikos.icatch.console_log_level&nbsp;=&nbsp;INFO&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.console_file_name = tm.out
com.atomikos.icatch.log_base_name = tmlog
com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm
com.atomikos.icatch.console_log_level = INFO
</pre>
<br />
<br />
随后，是Spring上下文配置，建立一个名为ApplicationContext-atomikos.xml的Spring上下文 <br />
<br />
ApplicationContext-atomikos.xml <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147599#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;?xml&nbsp;version=</span><span class="string">"1.0"</span><span>&nbsp;encoding=</span><span class="string">"UTF-8"</span><span>?&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;beans&nbsp;xmlns=</span><span class="string">"http://www.springframework.org/schema/beans"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xsi=</span><span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;xsi:schemaLocation=</span><span class="string">"http://www.springframework.org/schema/beans&nbsp;http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;XA&nbsp;Datasource&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"datasource1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.atomikos.jdbc.SimpleDataSourceBean"</span><span>&nbsp;init-method=</span><span class="string">"init"</span><span>&nbsp;destroy-method=</span><span class="string">"close"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"uniqueResourceName"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;mysql/main&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"xaDataSourceClassName"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;com.mysql.jdbc.jdbc2.optional.MysqlXADataSource&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"xaDataSourceProperties"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;URL=jdbc:mysql:</span><span class="comment">//localhost:3306/test;user=root;password=admin&lt;/value&gt;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"exclusiveConnectionMode"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;</span><span class="keyword">true</span><span>&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"connectionPoolSize"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;</span><span class="number">3</span><span>&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"validatingQuery"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;SELECT&nbsp;</span><span class="number">1</span><span>&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"datasource2"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.atomikos.jdbc.SimpleDataSourceBean"</span><span>&nbsp;init-method=</span><span class="string">"init"</span><span>&nbsp;destroy-method=</span><span class="string">"close"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"uniqueResourceName"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;mysql/news&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"xaDataSourceClassName"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;com.mysql.jdbc.jdbc2.optional.MysqlXADataSource&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"xaDataSourceProperties"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;URL=jdbc:mysql:</span><span class="comment">//localhost:3306/test2;user=root;password=admin&lt;/value&gt;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"exclusiveConnectionMode"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;</span><span class="keyword">true</span><span>&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"connectionPoolSize"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;</span><span class="number">3</span><span>&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"validatingQuery"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;SELECT&nbsp;</span><span class="number">1</span><span>&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"template1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.jdbc.core.JdbcTemplate"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dataSource"</span><span>&nbsp;ref=</span><span class="string">"datasource1"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"template2"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.jdbc.core.JdbcTemplate"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dataSource"</span><span>&nbsp;ref=</span><span class="string">"datasource2"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"atomikosTransactionManager"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.atomikos.icatch.jta.UserTransactionManager"</span><span>&nbsp;init-method=</span><span class="string">"init"</span><span>&nbsp;destroy-method=</span><span class="string">"close"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"forceShutdown"</span><span>&gt;&lt;value&gt;</span><span class="keyword">true</span><span>&lt;/value&gt;&lt;/property&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"atomikosUserTransaction"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.atomikos.icatch.jta.UserTransactionImp"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionTimeout"</span><span>&nbsp;value=</span><span class="string">"300"</span><span>/&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"springTransactionManager"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.transaction.jta.JtaTransactionManager"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionManager"</span><span>&gt;&lt;ref&nbsp;bean=</span><span class="string">"atomikosTransactionManager"</span><span>&nbsp;&nbsp;/&gt;&lt;/property&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"userTransaction"</span><span>&gt;&lt;ref&nbsp;bean=</span><span class="string">"atomikosUserTransaction"</span><span>&nbsp;&nbsp;/&gt;&lt;/property&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"dao1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.xa.dao.UserDao1"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"jdbcTemplate"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref&nbsp;bean=</span><span class="string">"template1"</span><span>&gt;&lt;/ref&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"dao2"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.xa.dao.UserDao2"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"jdbcTemplate"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref&nbsp;bean=</span><span class="string">"template2"</span><span>&gt;&lt;/ref&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"userServiceTarget"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.xa.service.UserServiceImpl"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dao1"</span><span>&nbsp;ref=</span><span class="string">"dao1"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dao2"</span><span>&nbsp;ref=</span><span class="string">"dao2"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"userTest"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.transaction.interceptor.TransactionProxyFactoryBean"</span><span>&gt;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionManager"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref&nbsp;bean=</span><span class="string">"springTransactionManager"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"target"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref&nbsp;bean=</span><span class="string">"userServiceTarget"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionAttributes"</span><span>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop&nbsp;key=</span><span class="string">"insert*"</span><span>&gt;PROPAGATION_REQUIRED,-Exception&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/beans&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"&gt;
&lt;!-- XA Datasource --&gt;
&lt;bean id="datasource1" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close"&gt;
&lt;property name="uniqueResourceName"&gt;
&lt;value&gt;mysql/main&lt;/value&gt;
&lt;/property&gt;
&lt;property name="xaDataSourceClassName"&gt;
&lt;value&gt;com.mysql.jdbc.jdbc2.optional.MysqlXADataSource&lt;/value&gt;
&lt;/property&gt;
&lt;property name="xaDataSourceProperties"&gt;
&lt;value&gt;URL=jdbc:mysql://localhost:3306/test;user=root;password=admin&lt;/value&gt;
&lt;/property&gt;
&lt;property name="exclusiveConnectionMode"&gt;
&lt;value&gt;true&lt;/value&gt;
&lt;/property&gt;
&lt;property name="connectionPoolSize"&gt;
&lt;value&gt;3&lt;/value&gt;
&lt;/property&gt;
&lt;property name="validatingQuery"&gt;
&lt;value&gt;SELECT 1&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="datasource2" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close"&gt;
&lt;property name="uniqueResourceName"&gt;
&lt;value&gt;mysql/news&lt;/value&gt;
&lt;/property&gt;
&lt;property name="xaDataSourceClassName"&gt;
&lt;value&gt;com.mysql.jdbc.jdbc2.optional.MysqlXADataSource&lt;/value&gt;
&lt;/property&gt;
&lt;property name="xaDataSourceProperties"&gt;
&lt;value&gt;URL=jdbc:mysql://localhost:3306/test2;user=root;password=admin&lt;/value&gt;
&lt;/property&gt;
&lt;property name="exclusiveConnectionMode"&gt;
&lt;value&gt;true&lt;/value&gt;
&lt;/property&gt;
&lt;property name="connectionPoolSize"&gt;
&lt;value&gt;3&lt;/value&gt;
&lt;/property&gt;
&lt;property name="validatingQuery"&gt;
&lt;value&gt;SELECT 1&lt;/value&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="template1" class="org.springframework.jdbc.core.JdbcTemplate"&gt;
&lt;property name="dataSource" ref="datasource1" /&gt;
&lt;/bean&gt;
&lt;bean id="template2" class="org.springframework.jdbc.core.JdbcTemplate"&gt;
&lt;property name="dataSource" ref="datasource2" /&gt;
&lt;/bean&gt;
&lt;bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"&gt;
&lt;property name="forceShutdown"&gt;&lt;value&gt;true&lt;/value&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"&gt;
&lt;property name="transactionTimeout" value="300"/&gt;
&lt;/bean&gt;
&lt;bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"&gt;
&lt;property name="transactionManager"&gt;&lt;ref bean="atomikosTransactionManager"  /&gt;&lt;/property&gt;
&lt;property name="userTransaction"&gt;&lt;ref bean="atomikosUserTransaction"  /&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="dao1" class="com.xa.dao.UserDao1"&gt;
&lt;property name="jdbcTemplate"&gt;
&lt;ref bean="template1"&gt;&lt;/ref&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="dao2" class="com.xa.dao.UserDao2"&gt;
&lt;property name="jdbcTemplate"&gt;
&lt;ref bean="template2"&gt;&lt;/ref&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;!-- --&gt;
&lt;bean id="userServiceTarget" class="com.xa.service.UserServiceImpl"&gt;
&lt;property name="dao1" ref="dao1"/&gt;
&lt;property name="dao2" ref="dao2"/&gt;
&lt;/bean&gt;
&lt;bean id="userTest" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
&lt;property name="transactionManager"&gt;
&lt;ref bean="springTransactionManager"/&gt;
&lt;/property&gt;
&lt;property name="target"&gt;
&lt;ref bean="userServiceTarget"/&gt;
&lt;/property&gt;
&lt;property name="transactionAttributes"&gt;
&lt;props&gt;
&lt;prop key="insert*"&gt;PROPAGATION_REQUIRED,-Exception&lt;/prop&gt;
&lt;/props&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/beans&gt;
</pre>
<br />
<br />
看上下文中的代码，很大部分和JOTM的相似，atomikos使用com.atomikos.jdbc.SimpleDataSourceBean类来创建datasource bean，这里需要特别注意 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147599#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;property&nbsp;name=</span><span class="string">"uniqueResourceName"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;mysql/main&lt;/value&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;property name="uniqueResourceName"&gt;
&lt;value&gt;mysql/main&lt;/value&gt;
&lt;/property&gt;
</pre>
<br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147599#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;property&nbsp;name=</span><span class="string">"uniqueResourceName"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;mysql/news&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/property&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;property name="uniqueResourceName"&gt;
&lt;value&gt;mysql/news&lt;/value&gt;
&lt;/property&gt;
</pre>
<br />
上面的代码为每个Datasource配置了一个唯一的名称，名称不允许相同，否则将会使用同一个datasource，而不会出现异常。 <br />
<br />
另外在配置文件中定义了Atomikos的事务管理器，并在Spring的JtaTransactionManager中引用 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147599#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;id=</span><span class="string">"atomikosTransactionManager"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.atomikos.icatch.jta.UserTransactionManager"</span><span>&nbsp;init-method=</span><span class="string">"init"</span><span>&nbsp;destroy-method=</span><span class="string">"close"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"forceShutdown"</span><span>&gt;&lt;value&gt;</span><span class="keyword">true</span><span>&lt;/value&gt;&lt;/property&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"atomikosUserTransaction"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.atomikos.icatch.jta.UserTransactionImp"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionTimeout"</span><span>&nbsp;value=</span><span class="string">"300"</span><span>/&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"springTransactionManager"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.transaction.jta.JtaTransactionManager"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionManager"</span><span>&gt;&lt;ref&nbsp;bean=</span><span class="string">"atomikosTransactionManager"</span><span>&nbsp;&nbsp;/&gt;&lt;/property&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"userTransaction"</span><span>&gt;&lt;ref&nbsp;bean=</span><span class="string">"atomikosUserTransaction"</span><span>&nbsp;&nbsp;/&gt;&lt;/property&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"&gt;
&lt;property name="forceShutdown"&gt;&lt;value&gt;true&lt;/value&gt;&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"&gt;
&lt;property name="transactionTimeout" value="300"/&gt;
&lt;/bean&gt;
&lt;bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"&gt;
&lt;property name="transactionManager"&gt;&lt;ref bean="atomikosTransactionManager"  /&gt;&lt;/property&gt;
&lt;property name="userTransaction"&gt;&lt;ref bean="atomikosUserTransaction"  /&gt;&lt;/property&gt;
&lt;/bean&gt;
</pre>
<br />
<br />
其它的代码没什么特别，和JOTM配置基本相同，JdbcTemplate，DAO，Service，事务代理等等.... <br />
<br />
仍然使用TestXa.java，修改成引用ApplicationContext-atomikos.xml的上下文配置 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147599#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">protected</span><span>&nbsp;String[]&nbsp;getConfigLocations()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//return&nbsp;new&nbsp;String[]&nbsp;{&nbsp;"classpath:ApplicationContext-jotm.xml"&nbsp;}; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;String[]&nbsp;{&nbsp;</span><span class="string">"classpath:ApplicationContext-atomikos.xml"</span><span>&nbsp;}; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">protected String[] getConfigLocations() {
//return new String[] { "classpath:ApplicationContext-jotm.xml" };
return new String[] { "classpath:ApplicationContext-atomikos.xml" };
}
</pre>
<br />
<br />
运行test，然后查看数据库状态， <br />
然后修改方法参数使其不违反数据库约束，再运行Test观察数据库 ：）。 
<img src ="http://www.blogjava.net/zjrstar/aggbug/247924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-12-23 15:47 <a href="http://www.blogjava.net/zjrstar/archive/2008/12/23/247924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转贴]Spring JTA应用之JOTM配置</title><link>http://www.blogjava.net/zjrstar/archive/2008/12/23/247922.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Tue, 23 Dec 2008 07:44:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/12/23/247922.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/247922.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/12/23/247922.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/247922.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/247922.html</trackback:ping><description><![CDATA[原文地址：http://tom-duan.javaeye.com/blog/147594<br />
<br />
JOTM(Java Open Transaction Manager)是ObjectWeb的一个开源JTA实现，本身也是开源应用程序服务器JOnAS(Java Open Application Server)的一部分，为其提供JTA分布式事务的功能。Spring对JOTM提供了较好的支持，提供了一个org.springframework.transaction.jta.JotmFactoryBean的支持类，在Spring2.0中也包含了JOTM相关的一些library。 <br />
<br />
jotm的下载地址为http://jotm.objectweb.org,最新版本为2.0.10. <br />
<br />
下载完成后解压缩，然后打开jotm下面conf文件夹，拷贝carol.properties文件到classpath中，并修改这个文件如下 <br />
carol.properties <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147594#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>#&nbsp;</span><span class="keyword">do</span><span>&nbsp;not&nbsp;use&nbsp;CAROL&nbsp;JNDI&nbsp;wrapper&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>carol.start.jndi=</span><span class="keyword">false</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>#&nbsp;</span><span class="keyword">do</span><span>&nbsp;not&nbsp;start&nbsp;a&nbsp;name&nbsp;server&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>carol.start.ns=</span><span class="keyword">false</span><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>#&nbsp;Naming&nbsp;Factory &nbsp;&nbsp;</span></li>
    <li><span>carol.jndi.java.naming.factory.url.pkgs=org.apache.naming&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code"># do not use CAROL JNDI wrapper
carol.start.jndi=false
# do not start a name server
carol.start.ns=false
# Naming Factory
carol.jndi.java.naming.factory.url.pkgs=org.apache.naming
</pre>
<br />
上面配置文件的目的是不使用JNDI的方式来加载JOTM的配置，当然也可以根据需要选择其它的一些配置，例如JTOM所提供的默认配置。 <br />
<br />
然后开始在Spring上下文中配置JOTM，在classpath中建立一个ApplicationContext-jotm.xml，配置如下 <br />
<br />
ApplicationContext-jotm.xml <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147594#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;?xml&nbsp;version=</span><span class="string">"1.0"</span><span>&nbsp;encoding=</span><span class="string">"UTF-8"</span><span>?&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;beans&nbsp;xmlns=</span><span class="string">"http://www.springframework.org/schema/beans"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;xmlns:xsi=</span><span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;xsi:schemaLocation=</span><span class="string">"http://www.springframework.org/schema/beans&nbsp;http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"jotm"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.transaction.jta.JotmFactoryBean"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"txManager"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.transaction.jta.JtaTransactionManager"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"userTransaction"</span><span>&nbsp;ref=</span><span class="string">"jotm"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"ds1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.enhydra.jdbc.pool.StandardXAPoolDataSource"</span><span>&nbsp;destroy-method=</span><span class="string">"shutdown"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dataSource"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.enhydra.jdbc.standard.StandardXADataSource"</span><span>&nbsp;destroy-method=</span><span class="string">"shutdown"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionManager"</span><span>&nbsp;ref=</span><span class="string">"jotm"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"driverName"</span><span>&nbsp;value=</span><span class="string">"com.mysql.jdbc.Driver"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"url"</span><span>&nbsp;value=</span><span class="string">"jdbc:MySQL://localhost:3306/test"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"user"</span><span>&nbsp;value=</span><span class="string">"root"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"password"</span><span>&nbsp;value=</span><span class="string">"admin"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"ds2"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.enhydra.jdbc.pool.StandardXAPoolDataSource"</span><span>&nbsp;destroy-method=</span><span class="string">"shutdown"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dataSource"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.enhydra.jdbc.standard.StandardXADataSource"</span><span>&nbsp;destroy-method=</span><span class="string">"shutdown"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionManager"</span><span>&nbsp;ref=</span><span class="string">"jotm"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"driverName"</span><span>&nbsp;value=</span><span class="string">"com.mysql.jdbc.Driver"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"url"</span><span>&nbsp;value=</span><span class="string">"jdbc:MySQL://localhost:3306/test2"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"user"</span><span>&nbsp;value=</span><span class="string">"root"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"password"</span><span>&nbsp;value=</span><span class="string">"admin"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"template1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.jdbc.core.JdbcTemplate"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dataSource"</span><span>&nbsp;ref=</span><span class="string">"ds1"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"template2"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.jdbc.core.JdbcTemplate"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dataSource"</span><span>&nbsp;ref=</span><span class="string">"ds2"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"dao1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.xa.dao.UserDao1"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"jdbcTemplate"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref&nbsp;bean=</span><span class="string">"template1"</span><span>&gt;&lt;/ref&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"dao2"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.xa.dao.UserDao2"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"jdbcTemplate"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref&nbsp;bean=</span><span class="string">"template2"</span><span>&gt;&lt;/ref&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"userServiceTarget"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.xa.service.UserServiceImpl"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dao1"</span><span>&nbsp;ref=</span><span class="string">"dao1"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dao2"</span><span>&nbsp;ref=</span><span class="string">"dao2"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"userTest"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.transaction.interceptor.TransactionProxyFactoryBean"</span><span>&gt;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionManager"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref&nbsp;bean=</span><span class="string">"txManager"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"target"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ref&nbsp;bean=</span><span class="string">"userServiceTarget"</span><span>/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionAttributes"</span><span>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop&nbsp;key=</span><span class="string">"insert*"</span><span>&gt;PROPAGATION_REQUIRED,-Exception&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/beans&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"&gt;
&lt;bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/&gt;
&lt;bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"&gt;
&lt;property name="userTransaction" ref="jotm" /&gt;
&lt;/bean&gt;
&lt;bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&gt;
&lt;property name="dataSource"&gt;
&lt;bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&gt;
&lt;property name="transactionManager" ref="jotm" /&gt;
&lt;property name="driverName" value="com.mysql.jdbc.Driver" /&gt;
&lt;property name="url" value="jdbc:MySQL://localhost:3306/test" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="user" value="root" /&gt;
&lt;property name="password" value="admin" /&gt;
&lt;/bean&gt;
&lt;bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&gt;
&lt;property name="dataSource"&gt;
&lt;bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&gt;
&lt;property name="transactionManager" ref="jotm" /&gt;
&lt;property name="driverName" value="com.mysql.jdbc.Driver" /&gt;
&lt;property name="url" value="jdbc:MySQL://localhost:3306/test2" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="user" value="root" /&gt;
&lt;property name="password" value="admin" /&gt;
&lt;/bean&gt;
&lt;bean id="template1" class="org.springframework.jdbc.core.JdbcTemplate"&gt;
&lt;property name="dataSource" ref="ds1" /&gt;
&lt;/bean&gt;
&lt;bean id="template2" class="org.springframework.jdbc.core.JdbcTemplate"&gt;
&lt;property name="dataSource" ref="ds2" /&gt;
&lt;/bean&gt;
&lt;bean id="dao1" class="com.xa.dao.UserDao1"&gt;
&lt;property name="jdbcTemplate"&gt;
&lt;ref bean="template1"&gt;&lt;/ref&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="dao2" class="com.xa.dao.UserDao2"&gt;
&lt;property name="jdbcTemplate"&gt;
&lt;ref bean="template2"&gt;&lt;/ref&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="userServiceTarget" class="com.xa.service.UserServiceImpl"&gt;
&lt;property name="dao1" ref="dao1"/&gt;
&lt;property name="dao2" ref="dao2"/&gt;
&lt;/bean&gt;
&lt;bean id="userTest" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;
&lt;property name="transactionManager"&gt;
&lt;ref bean="txManager"/&gt;
&lt;/property&gt;
&lt;property name="target"&gt;
&lt;ref bean="userServiceTarget"/&gt;
&lt;/property&gt;
&lt;property name="transactionAttributes"&gt;
&lt;props&gt;
&lt;prop key="insert*"&gt;PROPAGATION_REQUIRED,-Exception&lt;/prop&gt;
&lt;/props&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/beans&gt;
</pre>
<br />
上面是一个完整的Spring上下文配置，可以看第一个bean &#8220;jotm&#8221;，实际上引用了Spring内部所提供的对JOTM支持的工厂类，参考下面的配置代码段 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147594#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;id=</span><span class="string">"jotm"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.transaction.jta.JotmFactoryBean"</span><span>/&gt;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/&gt;
</pre>
<br />
<br />
随后，配置了JTA事务管理器，并且在管理器中使用上面所配置的jotm，如下面的代码 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147594#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;id=</span><span class="string">"txManager"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.transaction.jta.JtaTransactionManager"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"userTransaction"</span><span>&nbsp;ref=</span><span class="string">"jotm"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;/bean&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"&gt;
&lt;property name="userTransaction" ref="jotm" /&gt;
&lt;/bean&gt;
</pre>
<br />
<br />
再接下来就是配置多个数据源了，使用jotm提供的org.enhydra.jdbc.pool.StandardXAPoolDataSource类，根据类名可以明确地看出它是用以配置多个数据源的啦,配置的代码如下 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147594#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;id=</span><span class="string">"ds1"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.enhydra.jdbc.pool.StandardXAPoolDataSource"</span><span>&nbsp;destroy-method=</span><span class="string">"shutdown"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dataSource"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.enhydra.jdbc.standard.StandardXADataSource"</span><span>&nbsp;destroy-method=</span><span class="string">"shutdown"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionManager"</span><span>&nbsp;ref=</span><span class="string">"jotm"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"driverName"</span><span>&nbsp;value=</span><span class="string">"com.mysql.jdbc.Driver"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"url"</span><span>&nbsp;value=</span><span class="string">"jdbc:MySQL://localhost:3306/test"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"user"</span><span>&nbsp;value=</span><span class="string">"root"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"password"</span><span>&nbsp;value=</span><span class="string">"admin"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"ds2"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.enhydra.jdbc.pool.StandardXAPoolDataSource"</span><span>&nbsp;destroy-method=</span><span class="string">"shutdown"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"dataSource"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.enhydra.jdbc.standard.StandardXADataSource"</span><span>&nbsp;destroy-method=</span><span class="string">"shutdown"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"transactionManager"</span><span>&nbsp;ref=</span><span class="string">"jotm"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"driverName"</span><span>&nbsp;value=</span><span class="string">"com.mysql.jdbc.Driver"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"url"</span><span>&nbsp;value=</span><span class="string">"jdbc:MySQL://localhost:3306/test2"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"user"</span><span>&nbsp;value=</span><span class="string">"root"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=</span><span class="string">"password"</span><span>&nbsp;value=</span><span class="string">"admin"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/bean&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&gt;
&lt;property name="dataSource"&gt;
&lt;bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&gt;
&lt;property name="transactionManager" ref="jotm" /&gt;
&lt;property name="driverName" value="com.mysql.jdbc.Driver" /&gt;
&lt;property name="url" value="jdbc:MySQL://localhost:3306/test" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="user" value="root" /&gt;
&lt;property name="password" value="admin" /&gt;
&lt;/bean&gt;
&lt;bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"&gt;
&lt;property name="dataSource"&gt;
&lt;bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"&gt;
&lt;property name="transactionManager" ref="jotm" /&gt;
&lt;property name="driverName" value="com.mysql.jdbc.Driver" /&gt;
&lt;property name="url" value="jdbc:MySQL://localhost:3306/test2" /&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="user" value="root" /&gt;
&lt;property name="password" value="admin" /&gt;
&lt;/bean&gt;
</pre>
<br />
这里配置的两个数据源都连接到本地的mysql，实际上可以连接到不同的db server和不同类型的数据库，已经经过测试，这里为了方便，在本地建立了两个不同的数据库(test,test2)做测试。 <br />
<br />
随后的配置基本上和普通的Spring上下文配置相同了，根据不同的数据源配置两个jdbcTemplate，两个dao分别引用不同的jdbcTemplate, 将两个dao注入到UserService中, 最后将service纳入事务管理,并在事务代理配置中配置回滚规则,意思为如遇异常，则强制回滚内容。配置如下所示 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147594#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;property&nbsp;name=</span><span class="string">"transactionAttributes"</span><span>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop&nbsp;key=</span><span class="string">"insert*"</span><span>&gt;PROPAGATION_REQUIRED,-Exception&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/props&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/property&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;property name="transactionAttributes"&gt;
&lt;props&gt;
&lt;prop key="insert*"&gt;PROPAGATION_REQUIRED,-Exception&lt;/prop&gt;
&lt;/props&gt;
&lt;/property&gt;
</pre>
<br />
<br />
这样，一个使用JOTM JTA事务的简单应用算大致成型了，最后，写一个JUnit，来测试一下结果 <br />
TestXa.java <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147594#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">package</span><span>&nbsp;com.xa; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="keyword">import</span><span>&nbsp;org.springframework.context.ApplicationContext; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;org.springframework.test.AbstractDependencyInjectionSpringContextTests; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="keyword">import</span><span>&nbsp;com.xa.service.UserService; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;TestXa&nbsp;</span><span class="keyword">extends</span><span>&nbsp;AbstractDependencyInjectionSpringContextTests &nbsp;&nbsp;</span></span></li>
    <li><span>{ &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;String[]&nbsp;getConfigLocations()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;String[]&nbsp;{&nbsp;</span><span class="string">"classpath:ApplicationContext-jotm.xml"</span><span>&nbsp;}; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;testInsertBothDatabase()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ApplicationContext&nbsp;ctx&nbsp;=&nbsp;</span><span class="keyword">this</span><span>.getApplicationContext(); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UserService&nbsp;ut&nbsp;=&nbsp;(UserService)ctx.getBean(</span><span class="string">"userTest"</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ut.insertBothDatabase(</span><span class="string">"1"</span><span>,&nbsp;</span><span class="keyword">null</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(Exception&nbsp;e)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">package com.xa;
import org.springframework.context.ApplicationContext;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import com.xa.service.UserService;
public class TestXa extends AbstractDependencyInjectionSpringContextTests
{
protected String[] getConfigLocations() {
return new String[] { "classpath:ApplicationContext-jotm.xml" };
}
public void testInsertBothDatabase() {
ApplicationContext ctx = this.getApplicationContext();
UserService ut = (UserService)ctx.getBean("userTest");
try {
ut.insertBothDatabase("1", null);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
</pre>
<br />
在test中，调用了UserService的insertBothDatabase方法，有两个参数，userId和UserName，另外在方法的实现中调用了两个使用不同数据源dao，分别向两个不同的数据库插入输入，而test2数据库的xa_test表中，name字段是不允许为空的，因此，在插入test2数据库时会失败. <br />
<br />
运行这个test，然后察看数据库结果：），test和test2数据库中都没有插入成功，看serviceImpl中的代码可以知道，逻辑上dao1会先于dao2执行，但是由于JTA事务，在dao2插入数据出现异常时整个事务被回滚，由于事务被配置在service层，dao1和dao2都被纳入一个事务进行管理，呵呵。修改一下方法的参数，修改为 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://tom-duan.javaeye.com/blog/147594#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>ut.insertBothDatabase(</span><span class="string">"1"</span><span>,&nbsp;</span><span class="string">"name1"</span><span>);&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">ut.insertBothDatabase("1", "name1");
</pre>
<br />
<br />
然后再试试test看数据库结果，如何？ <br />
<img src ="http://www.blogjava.net/zjrstar/aggbug/247922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-12-23 15:44 <a href="http://www.blogjava.net/zjrstar/archive/2008/12/23/247922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用AutowiringRequestProcessor整合struts和Spring2.0</title><link>http://www.blogjava.net/zjrstar/archive/2008/12/22/247747.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Mon, 22 Dec 2008 05:55:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/12/22/247747.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/247747.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/12/22/247747.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/247747.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/247747.html</trackback:ping><description><![CDATA[原文位置：http://downpour.javaeye.com/blog/24239<br />
<br />
论坛中用Struts＋Spring的人不少，以前的帖子也有问过Struts＋Spring的整合方式。前面的帖子中ReadOnly老大曾经提到过Spring2.0新增加的一个整合方式。今天简单把这几种整合方式小结一下。 <br />
<br />
在这之前，别忘了用一下Google大法，一般早有人会对类似的问题做过回答，果然，在ibm developworks上有一篇文章，一下子涵盖了三种整合方式，有兴趣的xdjm可以参考下面的链接：http://www-128.ibm.com/developerworks/cn/java/j-sr2.html。 <br />
<br />
下面着重谈一下Spring2.0新增的一个整个方式，我感觉挺不错，可以完全将Struts的配置和Spring的配置分离。具体步骤如下： <br />
1. 编写Spring的配置文件applicationContext.xml，简单起见，仅仅定义一个Service对象。 <br />
<div class="quote_title">引用</div>
<div class="quote_div"><br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"&gt; <br />
<br />
&lt;beans&gt; <br />
<br />
&lt;bean id="userService" class="com.bearingpoint.gdc.zero.service.impl.UserServiceImpl" /&gt; <br />
<br />
&lt;/beans&gt; <br />
</div>
<br />
这看上去就和普通的Spring配置文件没有任何分别。 <br />
2. 编写Struts的配置文件struts-config.xml，注意其中的controller的配置，用到了Spring2.0的新特性。 <br />
<div class="quote_title">引用</div>
<div class="quote_div"><br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />
&lt;!DOCTYPE struts-config <br />
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" <br />
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd" <br />
&gt; <br />
<br />
&lt;struts-config&gt; <br />
<br />
&lt;action-mappings&gt; <br />
<br />
&lt;action path="/addUser" <br />
type="com.bearingpoint.gdc.zero.action.user.AddUser" <br />
scope="request" <br />
&gt; <br />
&lt;forward name="success" path="/index.jsp" /&gt; <br />
&lt;/action&gt; <br />
<br />
&lt;/action-mappings&gt; <br />
<br />
&lt;controller processorClass="org.springframework.web.struts.AutowiringRequestProcessor" /&gt; <br />
<br />
&lt;/struts-config&gt; <br />
</div>
<br />
<br />
3. 然后为你的Struts的Action注入你需要的Service <br />
<div class="quote_title">引用</div>
<div class="quote_div"><br />
private UserService userService; <br />
<br />
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { <br />
User user = new User(); <br />
userService.addUser(user); <br />
return mapping.findForward("success"); <br />
} <br />
<br />
/** <br />
* @param userService <br />
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The userService to set. <br />
*/ <br />
public void setUserService(UserService userService) { <br />
this.userService = userService; <br />
} <br />
</div>
<br />
看上去你好像啥都没做，而事实上，注入工作已经由AutowiringRequestProcessor自动完成。 <br />
<br />
4. 编写web.xml进行测试。 <br />
<div class="quote_title">引用</div>
<div class="quote_div"><br />
?xml version="1.0" ?&gt; <br />
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"&gt; <br />
<br />
&lt;web-app&gt; <br />
<br />
&nbsp;&nbsp;&nbsp; &lt;context-param&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;/WEB-INF/classes/applicationContext.xml&lt;/param-value&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;/context-param&gt; <br />
<br />
&lt;listener&gt; <br />
&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt; <br />
&lt;/listener&gt; <br />
<br />
&lt;servlet&gt; <br />
&lt;servlet-name&gt;struts&lt;/servlet-name&gt; <br />
&lt;servlet-class&gt;org.apache.struts.action.ActionServlet&lt;/servlet-class&gt; <br />
&lt;init-param&gt; <br />
&lt;param-name&gt;config&lt;/param-name&gt; <br />
&lt;param-value&gt;/WEB-INF/classes/struts-config.xml&lt;/param-value&gt; <br />
&lt;/init-param&gt; <br />
&lt;init-param&gt; <br />
&lt;param-name&gt;detail&lt;/param-name&gt; <br />
&lt;param-value&gt;2&lt;/param-value&gt; <br />
&lt;/init-param&gt; <br />
&lt;init-param&gt; <br />
&lt;param-name&gt;validate&lt;/param-name&gt; <br />
&lt;param-value&gt;true&lt;/param-value&gt; <br />
&lt;/init-param&gt; <br />
&lt;load-on-startup&gt;2&lt;/load-on-startup&gt; <br />
&lt;/servlet&gt; <br />
<br />
&lt;servlet-mapping&gt; <br />
&lt;servlet-name&gt;struts&lt;/servlet-name&gt; <br />
&lt;url-pattern&gt;*.do&lt;/url-pattern&gt; <br />
&lt;/servlet-mapping&gt; <br />
<br />
&nbsp;&nbsp;&nbsp; &lt;welcome-file-list&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt; <br />
&nbsp;&nbsp;&nbsp; &lt;/welcome-file-list&gt; <br />
&lt;/web-app&gt; <br />
</div>
<br />
<br />
最后，启动Jetty进行测试，顺利运行通过！ <br />
<br />
看上去如此简单，配置起来也没有什么很特别的地方，只是按照常规来写你的Spring和Struts的配置文件就好了。 <br />
<br />
不过在这里还是说一下其中的要注意两个问题： <br />
1. 这种autowire的注入支持两种不同的方式，分别是byName和byType，默认是byType。我想这对于绝大多数开发者来说是够了。 <br />
2. 鉴于在http://www.javaeye.com/topic/15057中所提到的OpenSessionInView模式的失效的问题。我仔细看了一下Spring的源码。对于这种autowire的整合方式，不推荐在struts-config.xml文件中配置ContextLoaderPlugIn，而是采用web.xml中的ContextLoaderListener来加载Spring的初始化配置。否则，你的OpenSessionInView模式可能会失效。 
 <img src ="http://www.blogjava.net/zjrstar/aggbug/247747.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-12-22 13:55 <a href="http://www.blogjava.net/zjrstar/archive/2008/12/22/247747.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转贴:三种整合 Struts 应用程序与 Spring 的方式</title><link>http://www.blogjava.net/zjrstar/archive/2008/12/22/247746.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Mon, 22 Dec 2008 05:49:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/12/22/247746.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/247746.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/12/22/247746.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/247746.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/247746.html</trackback:ping><description><![CDATA[<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="100%">
            <h1>原文位置：http://www-128.ibm.com/developerworks/cn/java/j-sr2.html</h1>
            <h1>使用 Spring 更好地处理 Struts 动作</h1>
            <p id="subtitle"><em>三种整合 Struts 应用程序与 Spring 的方式</em></p>
            <img class="display-img" height="6" alt="" src="http://www.ibm.com/i/c.gif" width="1" /></td>
            <td class="no-print" width="192"></td>
        </tr>
    </tbody>
</table>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr valign="top">
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td width="100%">
            <p>级别： 中级</p>
            <p><a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#author" cmimpressionsent="1">George Franciscus</a> (<a href="mailto:george.franciscus@nexcel.ca?subject=使用 Spring 更好地处理 Struts 动作" cmimpressionsent="1">george.franciscus@nexcel.ca</a>), 负责人, Nexcel<br />
            </p>
            <p>2005 年 10 月 11 日</p>
            <blockquote><em>Struts Recipes</em> 的合著者 George Franciscus 将介绍另一个重大的 Struts 整合窍门 —— 这次是将 Struts 应用程序导入 Spring 框架。请跟随 George，他将向您展示如何改变 Struts 动作，使得管理 Struts 动作就像管理 Spring beans 那样。结果是一个增强的 web 框架，这个框架可以方便地利用 Spring AOP 的优势。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
            <p>您肯定已经听说过控制反转 (IOC) 设计模式，因为很长一段时间以来一直在流传关于它的信息。如果您在任何功能中使用过 Spring 框架，那么您就知道其原理的作用。在本文中，我利用这一原理把一个 Struts 应用程序注入 Spring 框架，您将亲身体会到 IOC 模式的强大。</p>
            <p>将一个 Struts 应用程序整合进 Spring 框架具有多方面的优点。首先，Spring 是为解决一些关于 JEE 的真实世界问题而设计的，比如复杂性、低性能和可测试性，等等。第二，Spring 框架包含一个 AOP 实现，允许您将面向方面技术应用于面向对象的代码。第三，一些人可能会说 Spring 框架只有<em>处理</em> Struts 比 Struts 处理自己好。但是这是观点问题，我演示三种将 Struts 应用程序整合到 Spring 框架的方法后，具体由您自己决定使用哪一种。</p>
            <p>我所演示的方法都是执行起来相对简单的，但是它们却具有明显不同的优点。我为每一种方法创建了一个独立而可用的例子，这样您就可以完全理解每种方法。请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#resources" cmimpressionsent="1">下载</a> 部分获得完整例子源代码。请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#resources" cmimpressionsent="1">参考资料</a>，下载 Struts MVC 和 Spring 框架。</p>
            <p><a name="N1008C"><span class="atitle">为什么 Spring 这么了不起？</span></a></p>
            <p>Spring 的创立者 Rod Johnson 以一种批判的眼光看待 Java&#8482; 企业软件开发，并且提议很多企业难题都能够通过战略地使用 IOC 模式（也称作依赖注入）来解决。当 Rod 和一个具有奉献精神的开放源码开发者团队将这个理论应用于实践时，结果就产生了 Spring 框架。简言之，Spring 是一个轻型的容器，利用它可以使用一个外部 XML 配置文件方便地将对象连接在一起。每个对象都可以通过显示一个 JavaBean 属性收到一个到依赖对象的引用，留给您的简单任务就只是在一个 XML 配置文件中把它们连接好。</p>
            <table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
                <tbody>
                    <tr>
                        <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
                        <td>
                        <table cellspacing="0" cellpadding="5" width="100%" border="1">
                            <tbody>
                                <tr>
                                    <td bgcolor="#eeeeee"><a name="N10099"><strong>IOC 和 Spring</strong></a><br />
                                    <p>IOC 是一种使应用程序逻辑外在化的设计模式，所以它是被注入而不是被写入客户机代码中。将 IOC 与接口编程应用结合，就像 Spring 框架那样，产生了一种架构，这种架构能够减少客户机对特定实现逻辑的依赖。请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#resources" cmimpressionsent="1">参考资料</a> 了解更多关于 IOC 和 Spring 的信息。</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p>依赖注入是一个强大的特性，但是 Spring 框架能够提供更多特性。Spring 支持可插拔的事务管理器，可以给您的事务处理提供更广泛的选择范围。它集成了领先的持久性框架，并且提供一个一致的异常层次结构。Spring 还提供了一种使用面向方面代码代替正常的面向对象代码的简单机制。</p>
            <p>Spring AOP 允许您使用<em>拦截器</em> 在一个或多个执行点上拦截应用程序逻辑。加强应用程序在拦截器中的日志记录逻辑会产生一个更可读的、实用的代码基础，所以拦截器广泛用于日志记录。您很快就会看到，为了处理横切关注点，Spring AOP 发布了它自己的拦截器，您也可以编写您自己的拦截器。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N100B0"><span class="atitle">整合 Struts 和 Spring</span></a></p>
            <p>与 Struts 相似，Spring 可以作为一个 MVC 实现。这两种框架都具有自己的优点和缺点，尽管大部分人同意 Struts 在 MVC 方面仍然是最好的。很多开发团队已经学会在时间紧迫的时候利用 Struts 作为构造高品质软件的基础。Struts 具有如此大的推动力，以至于开发团队宁愿整合 Spring 框架的特性，而不愿意转换成 Spring MVC。没必要进行转换对您来说是一个好消息。Spring 架构允许您将 Struts 作为 Web 框架连接到基于 Spring 的业务和持久层。最后的结果就是现在一切条件都具备了。</p>
            <p>在接下来的小窍门中，您将会了解到三种将 Struts MVC 整合到 Spring 框架的方法。我将揭示每种方法的缺陷并且对比它们的优点。 一旦您了解到所有三种方法的作用，我将会向您展示一个令人兴奋的应用程序，这个程序使用的是这三种方法中我最喜欢的一种。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N100BC"><span class="atitle">三个小窍门</span></a></p>
            <p>接下来的每种整合技术（或者窍门）都有自己的优点和特点。我偏爱其中的一种，但是我知道这三种都能够加深您对 Struts 和 Spring 的理解。在处理各种不同情况的时候，这将给您提供一个广阔的选择范围。方法如下：</p>
            <ul>
                <li>使用 Spring 的 <code>ActionSupport</code> 类整合 Structs
                <li>使用 Spring 的 <code>DelegatingRequestProcessor</code> 覆盖 Struts 的 <code>RequestProcessor </code>
                <li>将 Struts <code>Action</code> 管理委托给 Spring 框架 </li>
            </ul>
            <p><a name="N100E1"><span class="smalltitle">装载应用程序环境</span></a></p>
            <p>无论您使用哪种技术，都需要使用 Spring 的 <code>ContextLoaderPlugin</code> 为 Struts 的 <code>ActionServlet</code> 装载 Spring 应用程序环境。就像添加任何其他插件一样，简单地向您的 struts-config.xml 文件添加该插件，如下所示：</p>
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;plug-in className=
                        "org.springframework.web.struts.ContextLoaderPlugIn"&gt;
                        &lt;set-property property=
                        "contextConfigLocation" value="/WEB-INF/beans.xml"/&gt;
                        &lt;/plug-in&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>前面已经提到过，在 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#download" cmimpressionsent="1">下载</a> 部分，您能够找到这三个完全可使用的例子的完整源代码。每个例子都为一个书籍搜索应用程序提供一种不同的 Struts 和 Spring 的整合方法。您可以在这里看到例子的要点，但是您也可以下载应用程序以查看所有的细节。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N100FE"><span class="atitle">窍门 1. 使用 Spring 的 ActionSupport</span></a></p>
            <p>手动创建一个 Spring 环境是一种整合 Struts 和 Spring 的最直观的方式。为了使它变得更简单，Spring 提供了一些帮助。为了方便地获得 Spring 环境，<code>org.springframework.web.struts.ActionSupport</code> 类提供了一个 <code>getWebApplicationContext()</code> 方法。您所做的只是从 Spring 的 <code>ActionSupport</code> 而不是 Struts <code>Action</code> 类扩展您的动作，如清单 1 所示：</p>
            <br />
            <a name="N1011C"><strong>清单 1. 使用 ActionSupport 整合 Struts</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">package ca.nexcel.books.actions;
                        import java.io.IOException;
                        import javax.servlet.ServletException;
                        import javax.servlet.http.HttpServletRequest;
                        import javax.servlet.http.HttpServletResponse;
                        import org.apache.struts.action.ActionError;
                        import org.apache.struts.action.ActionErrors;
                        import org.apache.struts.action.ActionForm;
                        import org.apache.struts.action.ActionForward;
                        import org.apache.struts.action.ActionMapping;
                        import org.apache.struts.action.DynaActionForm;
                        import org.springframework.context.ApplicationContext;
                        import org.springframework.web.struts.ActionSupport;
                        import ca.nexcel.books.beans.Book;
                        import ca.nexcel.books.business.BookService;
                        public class SearchSubmit extends ActionSupport {   <span class="boldcode">|(1)</span>
                        public ActionForward execute(
                        ActionMapping mapping,
                        ActionForm form,
                        HttpServletRequest request,
                        HttpServletResponse response)
                        throws IOException, ServletException {
                        DynaActionForm searchForm = (DynaActionForm) form;
                        String isbn = (String) searchForm.get("isbn");
                        //the old fashion way
                        //BookService bookService = new BookServiceImpl();
                        ApplicationContext ctx =
                        getWebApplicationContext();    <span class="boldcode">|(2)</span>
                        BookService bookService =
                        (BookService) ctx.getBean("bookService");   <span class="boldcode">|(3)</span>
                        Book book = bookService.read(isbn.trim());
                        if (null == book) {
                        ActionErrors errors = new ActionErrors();
                        errors.add(ActionErrors.GLOBAL_ERROR,new ActionError
                        ("message.notfound"));
                        saveErrors(request, errors);
                        return mapping.findForward("failure") ;
                        }
                        request.setAttribute("book", book);
                        return mapping.findForward("success");
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>让我们快速思考一下这里到底发生了什么。在 (1) 处，我通过从 Spring 的 <code>ActionSupport</code> 类而不是 Struts 的 <code>Action</code> 类进行扩展，创建了一个新的 <code>Action</code>。在 (2) 处，我使用 <code>getWebApplicationContext()</code> 方法获得一个 <code>ApplicationContext</code>。为了获得业务服务，我使用在 (2) 处获得的环境在 (3) 处查找一个 Spring bean。</p>
            <p>这种技术很简单并且易于理解。不幸的是，它将 Struts 动作与 Spring 框架耦合在一起。如果您想替换掉 Spring，那么您必须重写代码。并且，由于 Struts 动作不在 Spring 的控制之下，所以它不能获得 Spring AOP 的优势。当使用多重独立的 Spring 环境时，这种技术可能有用，但是在大多数情况下，这种方法不如另外两种方法合适。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N10146"><span class="atitle">窍门 2. 覆盖 RequestProcessor</span></a></p>
            <p>将 Spring 从 Struts 动作中分离是一个更巧妙的设计选择。分离的一种方法是使用 <code>org.springframework.web.struts.DelegatingRequestProcessor</code> 类来覆盖 Struts 的 <code>RequestProcessor</code> 处理程序，如清单 2 所示：</p>
            <br />
            <a name="N1015C"><strong>清单 2. 通过 Spring 的 DelegatingRequestProcessor 进行整合</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
                        &lt;!DOCTYPE struts-config PUBLIC
                        "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
                        "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"&gt;
                        &lt;struts-config&gt;
                        &lt;form-beans&gt;
                        &lt;form-bean name="searchForm"
                        type="org.apache.struts.validator.DynaValidatorForm"&gt;
                        &lt;form-property name="isbn"    type="java.lang.String"/&gt;
                        &lt;/form-bean&gt;
                        &lt;/form-beans&gt;
                        &lt;global-forwards type="org.apache.struts.action.ActionForward"&gt;
                        &lt;forward   name="welcome"                path="/welcome.do"/&gt;
                        &lt;forward   name="searchEntry"            path="/searchEntry.do"/&gt;
                        &lt;forward   name="searchSubmit"           path="/searchSubmit.do"/&gt;
                        &lt;/global-forwards&gt;
                        &lt;action-mappings&gt;
                        &lt;action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/&gt;
                        &lt;action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/&gt;
                        &lt;action    path="/searchSubmit"
                        type="ca.nexcel.books.actions.SearchSubmit"
                        input="/searchEntry.do"
                        validate="true"
                        name="searchForm"&gt;
                        &lt;forward name="success" path="/WEB-INF/pages/detail.jsp"/&gt;
                        &lt;forward name="failure" path="/WEB-INF/pages/search.jsp"/&gt;
                        &lt;/action&gt;
                        &lt;/action-mappings&gt;
                        &lt;message-resources parameter="ApplicationResources"/&gt;
                        &lt;controller processorClass="org.springframework.web.struts.
                        DelegatingRequestProcessor"/&gt; <span class="boldcode">|(1)</span>
                        &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
                        &lt;set-property property="pathnames"
                        value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;
                        &lt;/plug-in&gt;
                        &lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;
                        &lt;set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/&gt;
                        &lt;/plug-in&gt;
                        &lt;/struts-config&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>我利用了 <code>&lt;controller&gt;</code> 标记来用 <code>DelegatingRequestProcessor</code> 覆盖默认的 Struts <code>RequestProcessor</code>。下一步是在我的 Spring 配置文件中注册该动作，如清单 3 所示：</p>
            <br />
            <a name="N10179"><strong>清单 3. 在 Spring 配置文件中注册一个动作</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
                        "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
                        &lt;beans&gt;
                        &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt;
                        &lt;bean name="/searchSubmit"
                        class="ca.nexcel.books.actions.SearchSubmit"&gt; <span class="boldcode">|(1)</span>
                        &lt;property name="bookService"&gt;
                        &lt;ref bean="bookService"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;/beans&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>注意：在 (1) 处，我使用名称属性注册了一个 bean，以匹配 struts-config 动作映射名称。<code>SearchSubmit</code> 动作揭示了一个 JavaBean 属性，允许 Spring 在运行时填充属性，如清单 4 所示：</p>
            <br />
            <a name="N1018E"><strong>清单 4. 具有 JavaBean 属性的 Struts 动作</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">package ca.nexcel.books.actions;
                        import java.io.IOException;
                        import javax.servlet.ServletException;
                        import javax.servlet.http.HttpServletRequest;
                        import javax.servlet.http.HttpServletResponse;
                        import org.apache.struts.action.Action;
                        import org.apache.struts.action.ActionError;
                        import org.apache.struts.action.ActionErrors;
                        import org.apache.struts.action.ActionForm;
                        import org.apache.struts.action.ActionForward;
                        import org.apache.struts.action.ActionMapping;
                        import org.apache.struts.action.DynaActionForm;
                        import ca.nexcel.books.beans.Book;
                        import ca.nexcel.books.business.BookService;
                        public class SearchSubmit extends Action {
                        private BookService bookService;
                        public BookService getBookService() {
                        return bookService;
                        }
                        public void setBookService(BookService bookService) { <span class="boldcode">| (1)</span>
                        this.bookService = bookService;
                        }
                        public ActionForward execute(
                        ActionMapping mapping,
                        ActionForm form,
                        HttpServletRequest request,
                        HttpServletResponse response)
                        throws IOException, ServletException {
                        DynaActionForm searchForm = (DynaActionForm) form;
                        String isbn = (String) searchForm.get("isbn");
                        Book book = getBookService().read(isbn.trim());  <span class="boldcode">|(2)</span>
                        if (null == book) {
                        ActionErrors errors = new ActionErrors();
                        errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound"));
                        saveErrors(request, errors);
                        return mapping.findForward("failure") ;
                        }
                        request.setAttribute("book", book);
                        return mapping.findForward("success");
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>在清单 4 中，您可以了解到如何创建 Struts 动作。在 (1) 处，我创建了一个 JavaBean 属性。<code>DelegatingRequestProcessor</code>自动地配置这种属性。这种设计使 Struts 动作并不知道它正被 Spring 管理，并且使您能够利用 Sping 的动作管理框架的所有优点。由于您的 Struts 动作注意不到 Spring 的存在，所以您不需要重写您的 Struts 代码就可以使用其他控制反转容器来替换掉 Spring。</p>
            <p><code>DelegatingRequestProcessor</code> 方法的确比第一种方法好，但是仍然存在一些问题。如果您使用一个不同的 <code>RequestProcessor</code>，则需要手动整合 Spring 的 <code>DelegatingRequestProcessor</code>。添加的代码会造成维护的麻烦并且将来会降低您的应用程序的灵活性。此外，还有过一些使用一系列命令来代替 Struts <code>RequestProcessor</code> 的传闻。 这种改变将会对这种解决方法的使用寿命造成负面的影响。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N101B4"><span class="atitle">窍门 3. 将动作管理委托给 Spring</span></a></p>
            <p>一个更好的解决方法是将 Strut 动作管理委托给 Spring。您可以通过在 <code>struts-config</code> 动作映射中注册一个代理来实现。代理负责在 Spring 环境中查找 Struts 动作。由于动作在 Spring 的控制之下，所以它可以填充动作的 JavaBean 属性，并为应用诸如 Spring 的 AOP 拦截器之类的特性带来了可能。 </p>
            <p>清单 5 中的 <code>Action</code> 类与清单 4 中的相同。但是 struts-config 有一些不同：</p>
            <br />
            <a name="N101CD"><strong>清单 5. Spring 整合的委托方法</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
                        &lt;!DOCTYPE struts-config PUBLIC
                        "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
                        "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"&gt;
                        &lt;struts-config&gt;
                        &lt;form-beans&gt;
                        &lt;form-bean name="searchForm"
                        type="org.apache.struts.validator.DynaValidatorForm"&gt;
                        &lt;form-property name="isbn"    type="java.lang.String"/&gt;
                        &lt;/form-bean&gt;
                        &lt;/form-beans&gt;
                        &lt;global-forwards type="org.apache.struts.action.ActionForward"&gt;
                        &lt;forward   name="welcome"                path="/welcome.do"/&gt;
                        &lt;forward   name="searchEntry"            path="/searchEntry.do"/&gt;
                        &lt;forward   name="searchSubmit"           path="/searchSubmit.do"/&gt;
                        &lt;/global-forwards&gt;
                        &lt;action-mappings&gt;
                        &lt;action    path="/welcome" forward="/WEB-INF/pages/welcome.htm"/&gt;
                        &lt;action    path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/&gt;
                        &lt;action    path="/searchSubmit"
                        type="org.springframework.web.struts.DelegatingActionProxy" <span class="boldcode">|(1)</span>
                        input="/searchEntry.do"
                        validate="true"
                        name="searchForm"&gt;
                        &lt;forward name="success" path="/WEB-INF/pages/detail.jsp"/&gt;
                        &lt;forward name="failure" path="/WEB-INF/pages/search.jsp"/&gt;
                        &lt;/action&gt;
                        &lt;/action-mappings&gt;
                        &lt;message-resources parameter="ApplicationResources"/&gt;
                        &lt;plug-in className="org.apache.struts.validator.ValidatorPlugIn"&gt;
                        &lt;set-property
                        property="pathnames"
                        value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/&gt;
                        &lt;/plug-in&gt;
                        &lt;plug-in
                        className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;
                        &lt;set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/&gt;
                        &lt;/plug-in&gt;
                        &lt;/struts-config&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>清单 5 是一个典型的 struts-config.xml 文件，只有一个小小的差别。它注册 Spring 代理类的名称，而不是声明动作的类名，如（1）处所示。DelegatingActionProxy 类使用动作映射名称查找 Spring 环境中的动作。这就是我们使用 <code>ContextLoaderPlugIn</code> 声明的环境。</p>
            <p>将一个 Struts 动作注册为一个 Spring bean 是非常直观的，如清单 6 所示。我利用动作映射使用 <code>&lt;bean&gt;</code> 标记的名称属性（在这个例子中是 "<code>/searchSubmit</code>"）简单地创建了一个 bean。这个动作的 JavaBean 属性像任何 Spring bean 一样被填充： </p>
            <br />
            <a name="N101ED"><strong>清单 6. 在 Spring 环境中注册一个 Struts 动作</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
                        "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
                        &lt;beans&gt;
                        &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt;
                        &lt;bean name="/searchSubmit"
                        class="ca.nexcel.books.actions.SearchSubmit"&gt;
                        &lt;property name="bookService"&gt;
                        &lt;ref bean="bookService"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;/beans&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N101F4"><span class="atitle">动作委托的优点</span></a></p>
            <p>动作委托解决方法是这三种方法中最好的。Struts 动作不了解 Spring，不对代码作任何改变就可用于非 Spring 应用程序中。<code>RequestProcessor</code> 的改变不会影响它，并且它可以利用 Spring AOP 特性的优点。 </p>
            <p>动作委托的优点不止如此。一旦让 Spring 控制您的 Struts 动作，您就可以使用 Spring 给动作补充更强的活力。例如，没有 Spring 的话，所有的 Struts 动作都必须是线程安全的。如果您设置 <code>&lt;bean&gt;</code> 标记的 singleton 属性为&#8220;false&#8221;，那么不管用何种方法，您的应用程序都将在每一个请求上有一个新生成的动作对象。您可能不需要这种特性，但是把它放在您的工具箱中也很好。您也可以利用 Spring 的生命周期方法。例如，当实例化 Struts 动作时，<code>&lt;bean&gt;</code> 标记的 init-method 属性被用于运行一个方法。类似地，在从容器中删除 bean 之前，destroy-method 属性执行一个方法。这些方法是管理昂贵对象的好办法，它们以一种与 Servlet 生命周期相同的方式进行管理。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N1020D"><span class="atitle">拦截 Struts</span></a></p>
            <p>前面提到过，通过将 Struts 动作委托给 Spring 框架而整合 Struts 和 Spring 的一个主要的优点是：您可以将 Spring 的 AOP 拦截器应用于您的 Struts 动作。通过将 Spring 拦截器应用于 Struts 动作，您可以用最小的代价处理横切关注点。</p>
            <p>虽然 Spring 提供很多内置拦截器，但是我将向您展示如何创建自己的拦截器并把它应用于一个 Struts 动作。为了使用拦截器，您需要做三件事：</p>
            <ol>
                <li>创建拦截器。
                <li>注册拦截器。
                <li>声明在何处拦截代码。 </li>
            </ol>
            <p>这看起来非常简单的几句话却非常强大。例如，在清单 7 中，我为 Struts 动作创建了一个日志记录拦截器。 这个拦截器在每个方法调用之前打印一句话：</p>
            <br />
            <a name="N1022D"><strong>清单 7. 一个简单的日志记录拦截器</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">package ca.nexcel.books.interceptors;
                        import org.springframework.aop.MethodBeforeAdvice;
                        import java.lang.reflect.Method;
                        public class LoggingInterceptor implements MethodBeforeAdvice {
                        public void before(Method method, Object[] objects, Object o) throws Throwable {
                        System.out.println("logging before!");
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>这个拦截器非常简单。<code>before()</code> 方法在拦截点中每个方法之前运行。在本例中，它打印出一句话，其实它可以做您想做的任何事。下一步就是在 Spring 配置文件中注册这个拦截器，如清单 8 所示：</p>
            <br />
            <a name="N1023F"><strong>清单 8. 在 Spring 配置文件中注册拦截器</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
                        "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
                        &lt;beans&gt;
                        &lt;bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/&gt;
                        &lt;bean name="/searchSubmit"
                        class="ca.nexcel.books.actions.SearchSubmit"&gt;
                        &lt;property name="bookService"&gt;
                        &lt;ref bean="bookService"/&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;!--  Interceptors --&gt;
                        &lt;bean name="logger"
                        class="ca.nexcel.books.interceptors.LoggingInterceptor"/&gt; <span class="boldcode">|(1)</span>
                        &lt;!-- AutoProxies --&gt;
                        &lt;bean name="loggingAutoProxy"
                        class="org.springframework.aop.framework.autoproxy.
                        BeanNameAutoProxyCreator"&gt; <span class="boldcode">|(2)</span>
                        &lt;property name="beanNames"&gt;
                        &lt;value&gt;/searchSubmit&lt;/valuesgt; <span class="boldcode">|(3)</span>
                        &lt;/property&gt;
                        &lt;property name="interceptorNames"&gt;
                        &lt;list&gt;
                        &lt;value&gt;logger&lt;/value&gt; <span class="boldcode">|(4)</span>
                        &lt;/list&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        &lt;/beans&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>您可能已经注意到了，清单 8 扩展了 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#code6" cmimpressionsent="1">清单 6</a> 中所示的应用程序以包含一个拦截器。具体细节如下：</p>
            <ul>
                <li>在 (1) 处，我注册了这个拦截器。
                <li>在 (2) 处，我创建了一个 bean 名称自动代理，它描述如何应用拦截器。还有其他的方法定义拦截点，但是这种方法常见而简便。
                <li>在 (3) 处，我将 Struts 动作注册为将被拦截的 bean。如果您想要拦截其他的 Struts 动作，则只需要在 "beanNames" 下面创建附加的 <code>&lt;value&gt;</code> 标记。
                <li>在 (4) 处，当拦截发生时，我执行了在 (1) 处创建的拦截器 bean 的名称。这里列出的所有拦截器都应用于&#8220;beanNames&#8221;。 </li>
            </ul>
            <p>就是这样。就像这个例子所展示的，将您的 Struts 动作置于 Spring 框架的控制之下，为处理您的 Struts 应用程序提供了一系列全新的选择。在本例中，使用动作委托可以轻松地利用 Spring 拦截器提高 Struts 应用程序中的日志记录能力。</p>
            <br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br />
                        <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td>
                    </tr>
                </tbody>
            </table>
            <table class="no-print" cellspacing="0" cellpadding="0" align="right">
                <tbody>
                    <tr align="right">
                        <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br />
                        <table cellspacing="0" cellpadding="0" border="0">
                            <tbody>
                                <tr>
                                    <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br />
                                    </td>
                                    <td valign="top" align="right"><a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#main" cmimpressionsent="1"><strong>回页首</strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <br />
            <p><a name="N1026F"><span class="atitle">结束语</span></a></p>
            <p>在本文中，您已经学习了将 Struts 动作整合到 Spring 框架中的三种窍门。使用 Spring 的 <code>ActionSupport</code> 来整合 Struts（第一种窍门中就是这样做的）简单而快捷，但是会将 Struts 动作与 Spring 框架耦合在一起。如果您需要将应用程序移植到一个不同的框架，则需要重写代码。第二种解决方法通过委托 <code>RequestProcessor</code> 巧妙地解开代码的耦合，但是它的可扩展性不强，并且当 Struts 的 <code>RequestProcessor</code> 变成一系列命令时，这种方法就持续不了很长时间。第三种方法是这三种方法中最好的：将 Struts 动作委托给 Spring 框架可以使代码解耦，从而使您可以在您的 Struts 应用程序中利用 Spring 的特性（比如日志记录拦截器）。</p>
            <p>三种 Struts-Spring 整合窍门中的每一种都被实现成一个完整可用的应用程序。请参阅 <a href="http://www-128.ibm.com/developerworks/cn/java/j-sr2.html#download" cmimpressionsent="1">下载</a> 部分仔细研究它们。</p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/zjrstar/aggbug/247746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-12-22 13:49 <a href="http://www.blogjava.net/zjrstar/archive/2008/12/22/247746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转贴： 解惑 spring 嵌套事务</title><link>http://www.blogjava.net/zjrstar/archive/2008/12/15/246364.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Mon, 15 Dec 2008 03:15:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/12/15/246364.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/246364.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/12/15/246364.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/246364.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/246364.html</trackback:ping><description><![CDATA[&nbsp;原文出处：<a href="http://www.javaeye.com/topic/35907">http://www.javaeye.com/topic/35907</a><br />
<br />
&nbsp;&nbsp; 在所有使用 spring 的应用中, 声明式事务管理可能是使用率最高的功能了, 但是, 从我观察到的情况看, <br />
绝大多数人并不能深刻理解事务声明中不同事务传播属性配置的的含义, 让我们来看一下 TransactionDefinition 接口中的定义 <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/35907#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Support&nbsp;a&nbsp;current&nbsp;transaction,&nbsp;create&nbsp;a&nbsp;new&nbsp;one&nbsp;if&nbsp;none&nbsp;exists. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Analogous&nbsp;to&nbsp;EJB&nbsp;transaction&nbsp;attribute&nbsp;of&nbsp;the&nbsp;same&nbsp;name. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;p&gt;This&nbsp;is&nbsp;typically&nbsp;the&nbsp;default&nbsp;setting&nbsp;of&nbsp;a&nbsp;transaction&nbsp;definition. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;PROPAGATION_REQUIRED&nbsp;=&nbsp;</span><span class="number">0</span><span>; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Support&nbsp;a&nbsp;current&nbsp;transaction,&nbsp;execute&nbsp;non-transactionally&nbsp;if&nbsp;none&nbsp;exists. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Analogous&nbsp;to&nbsp;EJB&nbsp;transaction&nbsp;attribute&nbsp;of&nbsp;the&nbsp;same&nbsp;name. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;p&gt;Note:&nbsp;For&nbsp;transaction&nbsp;managers&nbsp;with&nbsp;transaction&nbsp;synchronization, </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;PROPAGATION_SUPPORTS&nbsp;is&nbsp;slightly&nbsp;different&nbsp;from&nbsp;no&nbsp;transaction&nbsp;at&nbsp;all, </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;as&nbsp;it&nbsp;defines&nbsp;a&nbsp;transaction&nbsp;scopp&nbsp;that&nbsp;synchronization&nbsp;will&nbsp;apply&nbsp;for. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;As&nbsp;a&nbsp;consequence,&nbsp;the&nbsp;same&nbsp;resources&nbsp;(JDBC&nbsp;Connection,&nbsp;Hibernate&nbsp;Session,&nbsp;etc) </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;will&nbsp;be&nbsp;shared&nbsp;for&nbsp;the&nbsp;entire&nbsp;specified&nbsp;scope.&nbsp;Note&nbsp;that&nbsp;this&nbsp;depends&nbsp;on </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;the&nbsp;actual&nbsp;synchronization&nbsp;configuration&nbsp;of&nbsp;the&nbsp;transaction&nbsp;manager. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;PROPAGATION_SUPPORTS&nbsp;=&nbsp;</span><span class="number">1</span><span>; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Support&nbsp;a&nbsp;current&nbsp;transaction,&nbsp;throw&nbsp;an&nbsp;exception&nbsp;if&nbsp;none&nbsp;exists. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Analogous&nbsp;to&nbsp;EJB&nbsp;transaction&nbsp;attribute&nbsp;of&nbsp;the&nbsp;same&nbsp;name. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;PROPAGATION_MANDATORY&nbsp;=&nbsp;</span><span class="number">2</span><span>; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Create&nbsp;a&nbsp;new&nbsp;transaction,&nbsp;suspend&nbsp;the&nbsp;current&nbsp;transaction&nbsp;if&nbsp;one&nbsp;exists. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Analogous&nbsp;to&nbsp;EJB&nbsp;transaction&nbsp;attribute&nbsp;of&nbsp;the&nbsp;same&nbsp;name. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;p&gt;Note:&nbsp;Actual&nbsp;transaction&nbsp;suspension&nbsp;will&nbsp;not&nbsp;work&nbsp;on&nbsp;out-of-the-box </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;on&nbsp;all&nbsp;transaction&nbsp;managers.&nbsp;This&nbsp;in&nbsp;particular&nbsp;applies&nbsp;to&nbsp;JtaTransactionManager, </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;which&nbsp;requires&nbsp;the&nbsp;&lt;code&gt;javax.transaction.TransactionManager&lt;/code&gt;&nbsp;to&nbsp;be </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;made&nbsp;available&nbsp;it&nbsp;to&nbsp;it&nbsp;(which&nbsp;is&nbsp;server-specific&nbsp;in&nbsp;standard&nbsp;J2EE). </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;PROPAGATION_REQUIRES_NEW&nbsp;=&nbsp;</span><span class="number">3</span><span>; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Execute&nbsp;non-transactionally,&nbsp;suspend&nbsp;the&nbsp;current&nbsp;transaction&nbsp;if&nbsp;one&nbsp;exists. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Analogous&nbsp;to&nbsp;EJB&nbsp;transaction&nbsp;attribute&nbsp;of&nbsp;the&nbsp;same&nbsp;name. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;p&gt;Note:&nbsp;Actual&nbsp;transaction&nbsp;suspension&nbsp;will&nbsp;not&nbsp;work&nbsp;on&nbsp;out-of-the-box </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;on&nbsp;all&nbsp;transaction&nbsp;managers.&nbsp;This&nbsp;in&nbsp;particular&nbsp;applies&nbsp;to&nbsp;JtaTransactionManager, </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;which&nbsp;requires&nbsp;the&nbsp;&lt;code&gt;javax.transaction.TransactionManager&lt;/code&gt;&nbsp;to&nbsp;be </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;made&nbsp;available&nbsp;it&nbsp;to&nbsp;it&nbsp;(which&nbsp;is&nbsp;server-specific&nbsp;in&nbsp;standard&nbsp;J2EE). </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;PROPAGATION_NOT_SUPPORTED&nbsp;=&nbsp;</span><span class="number">4</span><span>; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Execute&nbsp;non-transactionally,&nbsp;throw&nbsp;an&nbsp;exception&nbsp;if&nbsp;a&nbsp;transaction&nbsp;exists. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Analogous&nbsp;to&nbsp;EJB&nbsp;transaction&nbsp;attribute&nbsp;of&nbsp;the&nbsp;same&nbsp;name. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;PROPAGATION_NEVER&nbsp;=&nbsp;</span><span class="number">5</span><span>; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Execute&nbsp;within&nbsp;a&nbsp;nested&nbsp;transaction&nbsp;if&nbsp;a&nbsp;current&nbsp;transaction&nbsp;exists, </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;behave&nbsp;like&nbsp;PROPAGATION_REQUIRED&nbsp;else.&nbsp;There&nbsp;is&nbsp;no&nbsp;analogous&nbsp;feature&nbsp;in&nbsp;EJB. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;p&gt;Note:&nbsp;Actual&nbsp;creation&nbsp;of&nbsp;a&nbsp;nested&nbsp;transaction&nbsp;will&nbsp;only&nbsp;work&nbsp;on&nbsp;specific </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;transaction&nbsp;managers.&nbsp;Out&nbsp;of&nbsp;the&nbsp;box,&nbsp;this&nbsp;only&nbsp;applies&nbsp;to&nbsp;the&nbsp;JDBC </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;DataSourceTransactionManager&nbsp;when&nbsp;working&nbsp;on&nbsp;a&nbsp;JDBC&nbsp;3.0&nbsp;driver. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Some&nbsp;JTA&nbsp;providers&nbsp;might&nbsp;support&nbsp;nested&nbsp;transactions&nbsp;as&nbsp;well. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;org.springframework.jdbc.datasource.DataSourceTransactionManager </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;PROPAGATION_NESTED&nbsp;=&nbsp;</span><span class="number">6</span><span>;&nbsp;&nbsp;</span></span> </li>
</ol>
</div>
<pre class="java" style="display: none" name="code">/**
* Support a current transaction, create a new one if none exists.
* Analogous to EJB transaction attribute of the same name.
* &lt;p&gt;This is typically the default setting of a transaction definition.
*/
int PROPAGATION_REQUIRED = 0;
/**
* Support a current transaction, execute non-transactionally if none exists.
* Analogous to EJB transaction attribute of the same name.
* &lt;p&gt;Note: For transaction managers with transaction synchronization,
* PROPAGATION_SUPPORTS is slightly different from no transaction at all,
* as it defines a transaction scopp that synchronization will apply for.
* As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)
* will be shared for the entire specified scope. Note that this depends on
* the actual synchronization configuration of the transaction manager.
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
*/
int PROPAGATION_SUPPORTS = 1;
/**
* Support a current transaction, throw an exception if none exists.
* Analogous to EJB transaction attribute of the same name.
*/
int PROPAGATION_MANDATORY = 2;
/**
* Create a new transaction, suspend the current transaction if one exists.
* Analogous to EJB transaction attribute of the same name.
* &lt;p&gt;Note: Actual transaction suspension will not work on out-of-the-box
* on all transaction managers. This in particular applies to JtaTransactionManager,
* which requires the &lt;code&gt;javax.transaction.TransactionManager&lt;/code&gt; to be
* made available it to it (which is server-specific in standard J2EE).
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_REQUIRES_NEW = 3;
/**
* Execute non-transactionally, suspend the current transaction if one exists.
* Analogous to EJB transaction attribute of the same name.
* &lt;p&gt;Note: Actual transaction suspension will not work on out-of-the-box
* on all transaction managers. This in particular applies to JtaTransactionManager,
* which requires the &lt;code&gt;javax.transaction.TransactionManager&lt;/code&gt; to be
* made available it to it (which is server-specific in standard J2EE).
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_NOT_SUPPORTED = 4;
/**
* Execute non-transactionally, throw an exception if a transaction exists.
* Analogous to EJB transaction attribute of the same name.
*/
int PROPAGATION_NEVER = 5;
/**
* Execute within a nested transaction if a current transaction exists,
* behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB.
* &lt;p&gt;Note: Actual creation of a nested transaction will only work on specific
* transaction managers. Out of the box, this only applies to the JDBC
* DataSourceTransactionManager when working on a JDBC 3.0 driver.
* Some JTA providers might support nested transactions as well.
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager
*/
int PROPAGATION_NESTED = 6;
</pre>
<br />
<br />
我们可以看到, 在 spring 中一共定义了六种事务传播属性, 如果你觉得看起来不够直观, 那么我来转贴一个满大街都有的翻译 <br />
<br />
<div class="quote_title">引用</div>
<div class="quote_div"><br />
PROPAGATION_REQUIRED -- 支持当前事务，如果当前没有事务，就新建一个事务。这是最常见的选择。 <br />
PROPAGATION_SUPPORTS -- 支持当前事务，如果当前没有事务，就以非事务方式执行。 <br />
PROPAGATION_MANDATORY -- 支持当前事务，如果当前没有事务，就抛出异常。 <br />
PROPAGATION_REQUIRES_NEW -- 新建事务，如果当前存在事务，把当前事务挂起。 <br />
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作，如果当前存在事务，就把当前事务挂起。 <br />
PROPAGATION_NEVER -- 以非事务方式执行，如果当前存在事务，则抛出异常。 <br />
PROPAGATION_NESTED -- 如果当前存在事务，则在嵌套事务内执行。如果当前没有事务，则进行与PROPAGATION_REQUIRED类似的操作。 <br />
前六个策略类似于EJB CMT，第七个（PROPAGATION_NESTED）是Spring所提供的一个特殊变量。 <br />
它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为（如Spring的DataSourceTransactionManager） <br />
</div>
<br />
<br />
在我所见过的误解中, 最常见的是下面这种: <br />
<br />
<div class="quote_title">引用</div>
<div class="quote_div"><br />
假如有两个业务接口 ServiceA 和 ServiceB, 其中 ServiceA 中有一个方法实现如下 <br />
<br />
/** <br />
* 事务属性配置为 PROPAGATION_REQUIRED <br />
*/ <br />
void methodA() { <br />
// 调用 ServiceB 的方法 <br />
ServiceB.methodB(); <br />
} <br />
<br />
那么如果 ServiceB 的 methodB&nbsp; 如果配置了事务, 就必须配置为 PROPAGATION_NESTED <br />
</div>
<br />
<br />
这种想法可能害了不少人, 认为 Service 之间应该避免互相调用, 其实根本不用担心这点，PROPAGATION_REQUIRED 已经说得很明白, <br />
如果当前线程中已经存在事务, 方法调用会加入此事务, 果当前没有事务，就新建一个事务, 所以 ServiceB#methodB() 的事务只要遵循最普通的规则配置为 PROPAGATION_REQUIRED 即可, 如果 ServiceB#methodB (我们称之为内部事务, 为下文打下基础) 抛了异常, 那么 ServiceA#methodA(我们称之为外部事务) 如果没有特殊配置此异常时事务提交 (即 +MyCheckedException的用法), 那么整个事务是一定要 rollback 的, 什么 Service 只能调 Dao 之类的言论纯属无稽之谈, spring 只负责配置了事务属性方法的拦截, 它怎么知道你这个方法是在 Service 还是 Dao 里 ? <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 说了这么半天, 那到底什么是真正的事务嵌套呢, 解释之前我们来看一下&nbsp; Juergen Hoeller 的原话 <br />
<br />
<div class="quote_title">Juergen Hoeller 写道</div>
<div class="quote_div"><br />
PROPAGATION_REQUIRES_NEW starts a new, independent "inner" transaction for the given scope. This transaction will be committed or rolled back completely independent from the outer transaction, having its own isolation scope, its own set of locks, etc. The outer transaction will get suspended at the beginning of the inner one, and resumed once the inner one has completed. <br />
<br />
Such independent inner transactions are for example used for id generation through manual sequences, where the access to the sequence table should happen in its own transactions, to keep the lock there as short as possible. The goal there is to avoid tying the sequence locks to the (potentially much longer running) outer transaction, with the sequence lock not getting released before completion of the outer transaction. <br />
<br />
PROPAGATION_NESTED on the other hand starts a "nested" transaction, which is a true subtransaction of the existing one. What will happen is that a savepoint will be taken at the start of the nested transaction. &#237;f the nested transaction fails, we will roll back to that savepoint. The nested transaction is part of of the outer transaction, so it will only be committed at the end of of the outer transaction. <br />
<br />
Nested transactions essentially allow to try some execution subpaths as subtransactions: rolling back to the state at the beginning of the failed subpath, continuing with another subpath or with the main execution path there - all within one isolated transaction, and not losing any previous work done within the outer transaction. <br />
<br />
For example, consider parsing a very large input file consisting of account transfer blocks: The entire file should essentially be parsed within one transaction, with one single commit at the end. But if a block fails, its transfers need to be rolled back, writing a failure marker somewhere. You could either start over the entire transaction every time a block fails, remembering which blocks to skip - or you mark each block as a nested transaction, only rolling back that specific set of operations, keeping the previous work of the outer transaction. The latter is of course much more efficient, in particular when a block at the end of the file fails. <br />
</div>
<br />
<br />
<div class="quote_title">Juergen Hoeller 写道</div>
<div class="quote_div"><br />
Rolling back the entire transaction is the choice of the demarcation code/config that started the outer transaction. <br />
<br />
So if an inner transaction throws an exception and is supposed to be rolled back (according to the rollback rules), the transaction will get rolled back to the savepoint taken at the start of the inner transaction. The immediate calling code can then decide to catch the exception and proceed down some other path within the outer transaction. <br />
<br />
If the code that called the inner transaction lets the exception propagate up the call chain, the exception will eventually reach the demarcation code of the outer transaction. At that point, the rollback rules of the outer transaction decide whether to trigger a rollback. That would be a rollback of the entire outer transaction then. <br />
<br />
So essentially, it depends on your exception handling. If you catch the exception thrown by the inner transaction, you can proceed down some other path within the outer transaction. If you let the exception propagate up the call chain, it's eventually gonna cause a rollback of the entire outer transaction. <br />
</div>
<br />
<br />
&nbsp;&nbsp;&nbsp; 也就是说, 最容易弄混淆的其实是 PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED, 那么这两种方式又有何区别呢? 我简单的翻译一下 Juergen Hoeller 的话 : <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <span style="color: red">PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行.</span> <br />
<br />
<br />
&nbsp;&nbsp;&nbsp; <span style="color: red">另一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务,&nbsp; 它是已经存在事务的一个真正的子事务. 潜套事务开始执行时,&nbsp; 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交.</span> <br />
<br />
&nbsp;&nbsp;&nbsp; <span style="color: red">由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会被 commit, 这个规则同样适用于 roll back.</span> <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 那么外部事务如何利用嵌套事务的 savepoint 特性呢, 我们用代码来说话 <br />
&nbsp;&nbsp;&nbsp; <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/35907#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>ServiceA&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;事务属性配置为&nbsp;PROPAGATION_REQUIRED </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">void</span><span>&nbsp;methodA()&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServiceB.methodB(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>ServiceB&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;事务属性配置为&nbsp;PROPAGATION_REQUIRES_NEW </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">void</span><span>&nbsp;methodB()&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </li>
</ol>
</div>
<pre class="java" style="display: none" name="code">	ServiceA {
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
ServiceB.methodB();
}
}
ServiceB {
/**
* 事务属性配置为 PROPAGATION_REQUIRES_NEW
*/
void methodB() {
}
}
</pre>
&nbsp;&nbsp;&nbsp; <br />
<br />
这种情况下, 因为 ServiceB#methodB 的事务属性为 PROPAGATION_REQUIRES_NEW, 所以两者不会发生任何关系, ServiceA#methodA 和 ServiceB#methodB 不会因为对方的执行情况而影响事务的结果, 因为它们根本就是两个事务, 在 ServiceB#methodB 执行时 ServiceA#methodA 的事务已经挂起了 (关于事务挂起的内容已经超出了本文的讨论范围, 有时间我会再写一些挂起的文章) . <br />
<br />
那么 PROPAGATION_NESTED 又是怎么回事呢? 继续看代码 <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/35907#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>ServiceA&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;事务属性配置为&nbsp;PROPAGATION_REQUIRED </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">void</span><span>&nbsp;methodA()&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServiceB.methodB(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>ServiceB&nbsp;{ &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;事务属性配置为&nbsp;PROPAGATION_NESTED </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">void</span><span>&nbsp;methodB()&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> </li>
</ol>
</div>
<pre class="java" style="display: none" name="code">	ServiceA {
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
ServiceB.methodB();
}
}
ServiceB {
/**
* 事务属性配置为 PROPAGATION_NESTED
*/
void methodB() {
}
}
</pre>
<br />
<br />
现在的情况就变得比较复杂了, ServiceB#methodB 的事务属性被配置为 PROPAGATION_NESTED, 此时两者之间又将如何协作呢? 从 Juergen Hoeller 的原话中我们可以找到答案, ServiceB#methodB 如果 rollback, 那么内部事务(即 ServiceB#methodB) 将回滚到它执行前的 SavePoint(注意, 这是本文中第一次提到它, 潜套事务中最核心的概念), 而外部事务(即 ServiceA#methodA) 可以有以下两种处理方式: <br />
<br />
1. 改写 ServiceA 如下 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/35907#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span>ServiceA&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;事务属性配置为&nbsp;PROPAGATION_REQUIRED </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">void</span><span>&nbsp;methodA()&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServiceB.methodB(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(SomeException)&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;执行其他业务,&nbsp;如&nbsp;ServiceC.methodC(); </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
<pre class="java" style="display: none" name="code">	ServiceA {
/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
try {
ServiceB.methodB();
} catch (SomeException) {
// 执行其他业务, 如 ServiceC.methodC();
}
}
}
</pre>
<br />
<br />
这种方式也是潜套事务最有价值的地方, 它起到了分支执行的效果, 如果 ServiceB.methodB 失败, 那么执行 ServiceC.methodC(), 而 ServiceB.methodB 已经回滚到它执行之前的 SavePoint, 所以不会产生脏数据(相当于此方法从未执行过), 这种特性可以用在某些特殊的业务中, 而 PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRES_NEW 都没有办法做到这一点. (题外话 : 看到这种代码, 似乎似曾相识, 想起了 prototype.js 中的 Try 函数 ) <br />
<br />
2. 代码不做任何修改, 那么如果内部事务(即 ServiceB#methodB) rollback, 那么首先 ServiceB.methodB 回滚到它执行之前的 SavePoint(在任何情况下都会如此), <br />
&nbsp;&nbsp; 外部事务(即 ServiceA#methodA) 将根据具体的配置决定自己是 commit 还是 rollback (+MyCheckedException). <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
上面大致讲述了潜套事务的使用场景, 下面我们来看如何在 spring 中使用 PROPAGATION_NESTED, 首先来看 AbstractPlatformTransactionManager <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/35907#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;*&nbsp;Create&nbsp;a&nbsp;TransactionStatus&nbsp;for&nbsp;an&nbsp;existing&nbsp;transaction. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span class="keyword">private</span><span>&nbsp;TransactionStatus&nbsp;handleExistingTransaction( &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TransactionDefinition&nbsp;definition,&nbsp;Object&nbsp;transaction,&nbsp;</span><span class="keyword">boolean</span><span>&nbsp;debugEnabled) &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throws</span><span>&nbsp;TransactionException&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;...&nbsp;省略 &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(definition.getPropagationBehavior()&nbsp;==&nbsp;TransactionDefinition.PROPAGATION_NESTED)&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(!isNestedTransactionAllowed())&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">throw</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;NestedTransactionNotSupportedException( &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="string">"Transaction&nbsp;manager&nbsp;does&nbsp;not&nbsp;allow&nbsp;nested&nbsp;transactions&nbsp;by&nbsp;default&nbsp;-&nbsp;"</span><span>&nbsp;+ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="string">"specify&nbsp;'nestedTransactionAllowed'&nbsp;property&nbsp;with&nbsp;value&nbsp;'true'"</span><span>); &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(debugEnabled)&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug(</span><span class="string">"Creating&nbsp;nested&nbsp;transaction&nbsp;with&nbsp;name&nbsp;["</span><span>&nbsp;+&nbsp;definition.getName()&nbsp;+&nbsp;</span><span class="string">"]"</span><span>); &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(useSavepointForNestedTransaction())&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Create&nbsp;savepoint&nbsp;within&nbsp;existing&nbsp;Spring-managed&nbsp;transaction, </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;through&nbsp;the&nbsp;SavepointManager&nbsp;API&nbsp;implemented&nbsp;by&nbsp;TransactionStatus. </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Usually&nbsp;uses&nbsp;JDBC&nbsp;3.0&nbsp;savepoints.&nbsp;Never&nbsp;activates&nbsp;Spring&nbsp;synchronization. </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DefaultTransactionStatus&nbsp;status&nbsp;= &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newTransactionStatus(definition,&nbsp;transaction,&nbsp;</span><span class="keyword">false</span><span>,&nbsp;</span><span class="keyword">false</span><span>,&nbsp;debugEnabled,&nbsp;</span><span class="keyword">null</span><span>); &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status.createAndHoldSavepoint(); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;status; &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">else</span><span>&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Nested&nbsp;transaction&nbsp;through&nbsp;nested&nbsp;begin&nbsp;and&nbsp;commit/rollback&nbsp;calls. </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;Usually&nbsp;only&nbsp;for&nbsp;JTA:&nbsp;Spring&nbsp;synchronization&nbsp;might&nbsp;get&nbsp;activated&nbsp;here </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;in&nbsp;case&nbsp;of&nbsp;a&nbsp;pre-existing&nbsp;JTA&nbsp;transaction. </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doBegin(transaction,&nbsp;definition); &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">boolean</span><span>&nbsp;newSynchronization&nbsp;=&nbsp;(</span><span class="keyword">this</span><span>.transactionSynchronization&nbsp;!=&nbsp;SYNCHRONIZATION_NEVER); &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;newTransactionStatus(definition,&nbsp;transaction,&nbsp;</span><span class="keyword">true</span><span>,&nbsp;newSynchronization,&nbsp;debugEnabled,&nbsp;</span><span class="keyword">null</span><span>); &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
<pre class="java" style="display: none" name="code">	/**
* Create a TransactionStatus for an existing transaction.
*/
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
... 省略
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
}
if (useSavepointForNestedTransaction()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
newTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
doBegin(transaction, definition);
boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
}
}
}
</pre>
<br />
&nbsp;&nbsp; <br />
一目了然 <br />
<br />
<span style="color: red">1. 我们要设置 transactionManager 的 nestedTransactionAllowed 属性为 true, 注意, 此属性默认为 false!!!</span> <br />
<br />
再看 AbstractTransactionStatus#createAndHoldSavepoint() 方法 <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;" href="http://www.javaeye.com/topic/35907#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="comment">/** </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;*&nbsp;Create&nbsp;a&nbsp;savepoint&nbsp;and&nbsp;hold&nbsp;it&nbsp;for&nbsp;the&nbsp;transaction. </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;*&nbsp;@throws&nbsp;org.springframework.transaction.NestedTransactionNotSupportedException </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;*&nbsp;if&nbsp;the&nbsp;underlying&nbsp;transaction&nbsp;does&nbsp;not&nbsp;support&nbsp;savepoints </span>&nbsp;</span>
    <li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;createAndHoldSavepoint()&nbsp;</span><span class="keyword">throws</span><span>&nbsp;TransactionException&nbsp;{ &nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;setSavepoint(getSavepointManager().createSavepoint()); &nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
<pre class="java" style="display: none" name="code">	/**
* Create a savepoint and hold it for the transaction.
* @throws org.springframework.transaction.NestedTransactionNotSupportedException
* if the underlying transaction does not support savepoints
*/
public void createAndHoldSavepoint() throws TransactionException {
setSavepoint(getSavepointManager().createSavepoint());
}
</pre>
<br />
<br />
&nbsp; 可以看到 Savepoint 是 SavepointManager.createSavepoint 实现的, 再看 SavepointManager 的层次结构, 发现 <br />
&nbsp; 其 Template 实现是 JdbcTransactionObjectSupport, 常用的 DatasourceTransactionManager, HibernateTransactionManager <br />
&nbsp; 中的 TransactonObject 都是它的子类 :&nbsp;<br />
<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp; JdbcTransactionObjectSupport 告诉我们必须要满足两个条件才能 createSavepoint : <br />
&nbsp; <br />
<span style="color: red">2. java.sql.Savepoint 必须存在, 即 jdk 版本要 1.4+ <br />
3. Connection.getMetaData().supportsSavepoints() 必须为 true, 即 jdbc drive 必须支持 JDBC 3.0 </span><br />
<br />
确保以上条件都满足后, 你就可以尝试使用 PROPAGATION_NESTED 了. (全文完) <br />
<img src ="http://www.blogjava.net/zjrstar/aggbug/246364.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-12-15 11:15 <a href="http://www.blogjava.net/zjrstar/archive/2008/12/15/246364.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转贴：【学习笔记】开源缓存包 EHCache  全接触</title><link>http://www.blogjava.net/zjrstar/archive/2008/08/14/222052.html</link><dc:creator>一叶笑天</dc:creator><author>一叶笑天</author><pubDate>Thu, 14 Aug 2008 08:59:00 GMT</pubDate><guid>http://www.blogjava.net/zjrstar/archive/2008/08/14/222052.html</guid><wfw:comment>http://www.blogjava.net/zjrstar/comments/222052.html</wfw:comment><comments>http://www.blogjava.net/zjrstar/archive/2008/08/14/222052.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/zjrstar/comments/commentRss/222052.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/zjrstar/services/trackbacks/222052.html</trackback:ping><description><![CDATA[原文地址：http://www.uusam.com/uu/blog/article.asp?id=60<br />
<br />
EHCache 是一个纯java的，在Hibernate2.1充当可插入的的在进程中的缓存，它具有以下缓存，最小的依赖性，全面的文特性：快速，简单，丰富的文档和测试用例。 <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;官方网站 http://ehcache.sourceforge.net/ <br />
<br />
－－－－－－－－－－－－－－－－－－－－－－－－－－<br />
－－－－－－－－－－使用简介－－－－－－－－－－－－<br />
－－－－－－－－－－－－－－－－－－－－－－－－－－<br />
&nbsp;&nbsp;&nbsp;&nbsp;ehcache-1.2 cacheNames 列表的取得；<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;方法一：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager.create();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[] cacheNames = CacheManager.getInstance().getCacheNames();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;方法二：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager manager = new CacheManager();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[] cacheNames = manager.getCacheNames();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;方法三：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager manager1 = new CacheManager("src/config/ehcache1.xml");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager manager2 = new CacheManager("src/config/ehcache2.xml");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[] cacheNamesForManager1 = manager1.getCacheNames();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[] cacheNamesForManager2 = manager2.getCacheNames();<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;ehcache-1.2 管理器各种建立的方法：<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;方法一：<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;CacheManager manager = new CacheManager();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;方法二：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager manager = new CacheManager("src/config/ehcache.xml");<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;方法三：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL url = getClass().getResource("/anotherconfigurationname.xml");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager manager = new CacheManager(url);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;方法四：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream fis = new FileInputStream(new File("src/config/ehcache.xml").getAbsolutePath());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager manager = new CacheManager(fis);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} finally {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fis.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;添加和删除缓存元素<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置一个名为test 的新cache,test属性为默认<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager singletonManager = CacheManager.create();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;singletonManager.addCache("testCache");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache test = singletonManager.getCache("testCache");<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置一个名为test 的新cache,并定义其属性 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager singletonManager = CacheManager.create();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache memoryOnlyCache = new Cache("testCache", 5000, false, false, 5, 2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;manager.addCache(memoryOnlyCache);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache test = singletonManager.getCache("testCache");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache 属性说明：<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;构造函数：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public Cache(java.lang.String name,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int maxElementsInMemory,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean overflowToDisk,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean eternal,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long timeToLiveSeconds,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long timeToIdleSeconds)<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;参数说明：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- 元素名字。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;maxElementsInMemory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 设定内存中创建对象的最大值。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;overflowToDisk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- 设置当内存中缓存达到 maxInMemory 限制时元素是否可写到磁盘<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eternal&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 设置元素（译注：内存中对象）是否永久驻留。如果是，将忽略超<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;时限制且元素永不消亡。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeToIdleSeconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 设置某个元素消亡前的停顿时间。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;也就是在一个元素消亡之前，两次访问时间的最大时间间隔值。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这只能在元素不是永久驻留时有效（译注：如果对象永恒不灭，则<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置该属性也无用）。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果该值是 0 就意味着元素可以停顿无穷长的时间。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeToLiveSeconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 为元素设置消亡前的生存时间。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也就是一个元素从构建到消亡的最大时间间隔值。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这只能在元素不是永久驻留时有效。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;删除缓存元素：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager singletonManager = CacheManager.create();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;singletonManager.removeCache("test");<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;关闭缓存管理器 CacheManager<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheManager.getInstance().shutdown();<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;对于缓存对象的操作：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;放入一个简单的对象到缓存元素；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Element element = new Element("key1", "value1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.put(element);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到一个序列化后的对象属性值；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Element element = cache.get("key1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serializable value = element.getValue();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到一个没有序列化后的对象属性值；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Element element = cache.get("key1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object value = element.getObjectValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;删除一个对象从元素；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Element element = new Element("key1", "value1"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.remove("key1");<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;对于永固性磁盘存储，立即存储到磁盘：<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.flush();<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;获得缓存大小：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到缓存的对象数量；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int elementsInMemory = cache.getSize();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到缓存对象占用内存的数量<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long elementsInMemory = cache.getMemoryStoreSize();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到缓存对对象占用磁盘的数量<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long elementsInMemory = cache.getDiskStoreSize();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;关于缓存的读取和丢失的记录<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到缓存读取的命中次数；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits = cache.getHitCount();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到内存中缓存读取的命中次数；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits = cache.getMemoryStoreHitCount();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到磁盘中缓存读取的命中次数；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits = cache.getDiskStoreCount();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到缓存读取的丢失次数；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits = cache.getMissCountNotFound();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到缓存读取的已经被销毁的对象丢失次数；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("sampleCache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits = cache.getMissCountExpired();<br />
<br />
－－－－－－－－－－－－－－－－－－－－－－－－－－<br />
－－－－－－－－－－简单例子－－－－－－－－－－－－<br />
－－－－－－－－－－－－－－－－－－－－－－－－－－<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;实战：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XML文件格式:<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ehcache&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;diskStore path="java.io.tmpdir"/&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;defaultCache<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;maxElementsInMemory="10000"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eternal="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeToIdleSeconds="120"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeToLiveSeconds="120"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;overflowToDisk="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diskPersistent="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;diskExpiryThreadIntervalSeconds="120"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memoryStoreEvictionPolicy="LRU"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;cache name="cache1"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="10000"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="2"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="3"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memoryStoreEvictionPolicy="LFU"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ehcache&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;源码：<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import java.io.Serializable;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import net.sf.ehcache.Cache;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import net.sf.ehcache.CacheManager;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import net.sf.ehcache.Element;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #############################################################################<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # DESCRIBE ehcache 缓存操作DEMO<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # AUTHOR&nbsp;&nbsp; 悠～游<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # DATE&nbsp;&nbsp;&nbsp;&nbsp; 2006-7-10<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # COMPANY&nbsp;&nbsp;FLX<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # PORJECT&nbsp;&nbsp;ehcache-demo<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #############################################################################<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public class Demo {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static CacheManager manager= new CacheManager();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *##############################################################################<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @DESCRIBE&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param args<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @throws InterruptedException<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *##############################################################################<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] args) throws InterruptedException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[] cacheNames = manager.getCacheNames();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("读取的缓存列表为：");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=0;i&lt;cacheNames.length;i++){ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("-- "+(i+1)+" "+cacheNames[i]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache cache = manager.getCache("cache1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Element element = new Element("key1", "value1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.put(element);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element = cache.get("key1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serializable value = element.getValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("序列化后的值为："+value.toString());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;element = cache.get("key1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object value1 = element.getObjectValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("未序列化的值为："+value1.toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int elementsInMemory = cache.getSize();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("得到缓存的对象数量："+elementsInMemory);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long elementsInMemory1 = cache.getMemoryStoreSize();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("得到缓存对象占用内存的数量："+elementsInMemory1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long elementsInMemory2 = cache.getDiskStoreSize();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("得到缓存对对象占用磁盘的数量："+elementsInMemory2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits = cache.getHitCount();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("得到缓存读取的命中次数："+hits);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits1 = cache.getMemoryStoreHitCount();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("得到内存中缓存读取的命中次数："+hits1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits2 =cache.getDiskStoreHitCount();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("得到磁盘中缓存读取的命中次数："+hits2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits3 = cache.getMissCountNotFound();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("得到缓存读取的丢失次数："+hits3);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int hits4 = cache.getMissCountExpired();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("得到缓存读取的已经被销毁的对象丢失次数："+hits4);&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
<img src ="http://www.blogjava.net/zjrstar/aggbug/222052.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/zjrstar/" target="_blank">一叶笑天</a> 2008-08-14 16:59 <a href="http://www.blogjava.net/zjrstar/archive/2008/08/14/222052.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>