﻿<?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-自然-文章分类-Spring</title><link>http://www.blogjava.net/masen/category/22616.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 26 Mar 2015 17:29:25 GMT</lastBuildDate><pubDate>Thu, 26 Mar 2015 17:29:25 GMT</pubDate><ttl>60</ttl><item><title>Spring事务管理器的应对 (转)</title><link>http://www.blogjava.net/masen/articles/423831.html</link><dc:creator>Masen</dc:creator><author>Masen</author><pubDate>Wed, 25 Mar 2015 10:07:00 GMT</pubDate><guid>http://www.blogjava.net/masen/articles/423831.html</guid><wfw:comment>http://www.blogjava.net/masen/comments/423831.html</wfw:comment><comments>http://www.blogjava.net/masen/articles/423831.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/masen/comments/commentRss/423831.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/masen/services/trackbacks/423831.html</trackback:ping><description><![CDATA[<div style="margin-bottom: 15px; font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 12px; line-height: 12px;"><h3><span style="font-size: 14px; line-height: 1.8em; color: red;"><span style="font-size: large;">Spring事务管理器的应对</span></span><span style="font-size: 14px; line-height: 1.8em;">&nbsp;</span></h3></div><div id="blog_content" style="font-size: 14px; line-height: 1.8em; font-family: Helvetica, Tahoma, Arial, sans-serif;"><br /><br />&nbsp;&nbsp; Spring抽象的DAO体系兼容多种数据访问技术，它们各有特色，各有千秋。像Hibernate是非常优秀的ORM实现方案，但对底层SQL的控制不太方便；而iBatis则通过模板化技术让你方便地控制SQL，但没有Hibernate那样高的开发效率；自由度最高的当然是直接使用Spring JDBC了，但它也是底层的，灵活的代价是代码的繁复。很难说哪种数据访问技术是最优秀的，只有在某种特定的场景下才能给出答案。所以在一个应用中，往往采用多个数据访问技术：一般是两种，一种采用ORM技术框架，而另一种采用偏JDBC的底层技术，两者珠联璧合，形成联合军种，共同御敌。&nbsp;<br />&nbsp;&nbsp; 但是，这种联合军种如何应对事务管理的问题呢？我们知道Spring为每种数据访问技术提供了相应的事务管理器，难道需要分别为它们配置对应的事务管理器吗？它们到底是如何协作和工作的呢？这些层出不穷的问题往往压制了开发人员使用联合军种的想法。&nbsp;<br />&nbsp;&nbsp; 其实，在这个问题上，我们低估了Spring事务管理的能力。如果你采用了一个高端ORM技术（Hibernate、JPA、JDO），同时采用一个JDBC技术（Spring JDBC、iBatis），由于前者的会话（Session）是对后者连接（Connection）的封装，Spring会&#8220;足够智能地&#8221;在同一个事务线程让前者的会话封装后者的连接。所以，我们只要直接采用前者的事务管理器就可以了。表10-1给出了混合数据访问技术框架所对应的事务管理器。&nbsp;<br /><table style="border-style: solid; border-color: #cccccc;"><tbody><tr><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">序&nbsp;&nbsp;&nbsp; 号</td><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">混合数据访问技术框架</td><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">事务管理器</td></tr><tr><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">1</td><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">Hibernate+ Spring JDBC或iBatis</td><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">org.springframework.orm.hibernate3.HibernateTransactionManager</td></tr><tr><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">2</td><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">JPA+Spring JDBC或iBatis</td><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">org.springframework.orm.jpa.JpaTransactionManager</td></tr><tr><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">3</td><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">JDO+Spring JDBC或iBatis</td><td style="font-size: 1em; border-style: solid; border-color: #cccccc; padding: 3px;">org.springframework.orm.jdo.JdoTransactionManager</td></tr></tbody></table><br /><br /><span style="color: red;"><span style="font-size: large;">Hibernate+Spring JDBC混合框架的事务管理</span>&nbsp;<br /></span><br /><br />&nbsp;&nbsp; 由于一般不会出现同时使用多个ORM框架的情况（如Hibernate+JPA），我们不拟对此命题展开论述，只重点研究ORM框架+JDBC框架的情况。Hibernate+Spring JDBC可能是被使用得最多的组合，本节我们通过实例观察事务管理的运作情况。&nbsp;<br /><div id="" style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace; width: 679px; margin-left: 9px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word;"><div><div style="padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin: 0px; font-weight: bold;">Java代码&nbsp;&nbsp;<a title="收藏这段代码" style="color: #006699; text-decoration: underline;"><img src="http://stamen.iteye.com/images/icon_star.png" alt="收藏代码" style="border: 0px;" /></a></div></div><ol start="1" style="font-size: 1em; line-height: 1.4em; margin-left: 0px; padding-top: 2px; padding-bottom: 2px; border: 1px solid #d1d7dc; color: #2b91af;"><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #7f0055;">package</span>&nbsp;com.baobaotao.mixdao;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&#8230;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #646464;">@Service</span>("userService")&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #7f0055;">public</span>&nbsp;<span style="color: #7f0055;">class</span>&nbsp;UserService&nbsp;<span style="color: #7f0055;">extends</span>&nbsp;BaseService&nbsp;{&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #646464;">@Autowired</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">private</span>&nbsp;HibernateTemplate&nbsp;hibernateTemplate;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #646464;">@Autowired</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">private</span>&nbsp;ScoreService&nbsp;scoreService;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">public</span>&nbsp;<span style="color: #7f0055;">void</span>&nbsp;logon(String&nbsp;userName)&nbsp;{&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="width: auto; border-width: 0px;">//&#9312;通过Hibernate技术访问数据</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("before&nbsp;updateLastLogonTime()..");&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;updateLastLogonTime(userName);&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("end&nbsp;updateLastLogonTime()..");&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="width: auto; border-width: 0px;">//&#9313;通过JDBC技术访问数据</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("before&nbsp;scoreService.addScore()..");&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scoreService.addScore(userName,&nbsp;<span style="color: #c00000;">20</span>);&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("end&nbsp;scoreService.addScore()..");&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">public</span>&nbsp;<span style="color: #7f0055;">void</span>&nbsp;updateLastLogonTime(String&nbsp;userName)&nbsp;{&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User&nbsp;user&nbsp;=&nbsp;hibernateTemplate.get(User.<span style="color: #7f0055;">class</span>,userName);&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.setLastLogonTime(System.currentTimeMillis());&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hibernateTemplate.update(user);&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="width: auto; border-width: 0px;">//&#9314;这句很重要，请看下文的分析</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hibernateTemplate.flush();&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">}&nbsp;&nbsp;</li></ol></div><br />&nbsp; 在&#9312;处，使用Hibernate操作数据，而在&#9313;处调用ScoreService#addScore()，该方法内部使用Spring JDBC操作数据。&nbsp;<br />&nbsp; 在&#9314;处，我们显式调用了flush()方法，将Session中的缓存同步到数据库中（即马上向数据库发送一条更新记录的SQL语句）。之所以要显式执行flush()方法，原因是在默认情况下，Hibernate对数据的更改只是记录在一级缓存中，要等到事务提交或显式调用flush()方法时才会将一级缓存中的数据同步到数据库中，而提交事务的操作发生在&nbsp;&nbsp; logon()方法返回前。如果所有针对数据库的更改操作都使用Hibernate，这种数据同步的延迟机制并不会产生任何问题。但是，我们在logon()方法中同时采用了Hibernate和Spring JDBC混合数据访问技术，Spring JDBC无法自动感知Hibernate一级缓存，所以如果不及时调用flush()方法将记录数据更改的一级缓存同步到数据库中，则&#9313;处通过Spring JDBC进行数据更改的结果将被Hibernate一级缓存中的更改覆盖掉，因为Hibernate一级缓存要等到logon()方法返回前才同步到数据库！&nbsp;<br />&nbsp;&nbsp; ScoreService使用Spring JDBC数据访问技术，其代码如下所示：&nbsp;<br /><div id="" style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace; width: 679px; margin-left: 9px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word;"><div><div style="padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin: 0px; font-weight: bold;">Java代码&nbsp;&nbsp;<a title="收藏这段代码" style="color: #006699; text-decoration: underline;"><img src="http://stamen.iteye.com/images/icon_star.png" alt="收藏代码" style="border: 0px;" /></a></div></div><ol start="1" style="font-size: 1em; line-height: 1.4em; margin-left: 0px; padding-top: 2px; padding-bottom: 2px; border: 1px solid #d1d7dc; color: #2b91af;"><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #7f0055;">package</span>&nbsp;com.baobaotao.mixdao;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #7f0055;">import</span>&nbsp;org.springframework.beans.factory.annotation.Autowired;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #7f0055;">import</span>&nbsp;org.springframework.jdbc.core.JdbcTemplate;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #7f0055;">import</span>&nbsp;org.springframework.stereotype.Service;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #7f0055;">import</span>&nbsp;org.apache.commons.dbcp.BasicDataSource;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #646464;">@Service</span>("scoreService")&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #7f0055;">public</span>&nbsp;<span style="color: #7f0055;">class</span>&nbsp;ScoreService&nbsp;<span style="color: #7f0055;">extends</span>&nbsp;BaseService{&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #646464;">@Autowired</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">private</span>&nbsp;JdbcTemplate&nbsp;jdbcTemplate;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #7f0055;">public</span>&nbsp;<span style="color: #7f0055;">void</span>&nbsp;addScore(String&nbsp;userName,&nbsp;<span style="color: #7f0055;">int</span>&nbsp;toAdd)&nbsp;{&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sql&nbsp;=&nbsp;"UPDATE&nbsp;t_user&nbsp;u&nbsp;SET&nbsp;u.score&nbsp;=&nbsp;u.score&nbsp;+&nbsp;?&nbsp;WHERE&nbsp;user_name&nbsp;=?";&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jdbcTemplate.update(sql,&nbsp;toAdd,&nbsp;userName);&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BasicDataSource&nbsp;basicDataSource&nbsp;=&nbsp;(BasicDataSource)&nbsp;jdbcTemplate.getDataSource();&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="width: auto; border-width: 0px;">//&#9312;查看此处数据库激活的连接数量</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("[scoreUserService.addScore]激活连接数量："&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+basicDataSource.getNumActive());&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">}&nbsp;&nbsp;</li></ol></div><br />&nbsp;&nbsp; Spring关键的配置文件代码如下所示：&nbsp;<br /><div id="" style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace; width: 679px; margin-left: 9px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; word-break: break-all; word-wrap: break-word;"><div><div style="padding-right: 3px; padding-bottom: 3px; padding-left: 3px; margin: 0px; font-weight: bold;">Xml代码&nbsp;&nbsp;<a title="收藏这段代码" style="color: #006699; text-decoration: underline;"><img src="http://stamen.iteye.com/images/icon_star.png" alt="收藏代码" style="border: 0px;" /></a></div></div><ol start="1" style="font-size: 1em; line-height: 1.4em; margin-left: 0px; padding-top: 2px; padding-bottom: 2px; border: 1px solid #d1d7dc; color: #2b91af;"><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&#8230;&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="width: auto; border-width: 0px;">&lt;!--&#9312;使用Hibernate事务管理器&nbsp;--&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #006699; font-weight: bold;">&lt;</span><span style="color: #006699; font-weight: bold;">bean</span>&nbsp;<span style="color: red;">id</span>=<span style="color: blue;">"hiberManager"</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red;">class</span>=<span style="color: blue;">"org.springframework.orm.hibernate3.HibernateTransactionManager"</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red;">p:sessionFactory-ref</span>=<span style="color: blue;">"sessionFactory"</span><span style="color: #006699; font-weight: bold;">/&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="width: auto; border-width: 0px;">&lt;!--&#9313;使UserService及ScoreService的公用方法都拥有事务&nbsp;--&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #006699; font-weight: bold;">&lt;</span><span style="color: #006699; font-weight: bold;">aop:config</span>&nbsp;<span style="color: red;">proxy-target-class</span>=<span style="color: blue;">"true"</span><span style="color: #006699; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #006699; font-weight: bold;">&lt;</span><span style="color: #006699; font-weight: bold;">aop:pointcut</span>&nbsp;<span style="color: red;">id</span>=<span style="color: blue;">"serviceJdbcMethod"</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red;">expression</span>=<span style="color: blue;">"within(com.baobaotao.mixdao.BaseService+)"</span><span style="color: #006699; font-weight: bold;">/&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #006699; font-weight: bold;">&lt;</span><span style="color: #006699; font-weight: bold;">aop:advisor</span>&nbsp;<span style="color: red;">pointcut-ref</span>=<span style="color: blue;">"serviceJdbcMethod"</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red;">advice-ref</span>=<span style="color: blue;">"hiberAdvice"</span><span style="color: #006699; font-weight: bold;">/&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #006699; font-weight: bold;">&lt;/</span><span style="color: #006699; font-weight: bold;">aop:config</span><span style="color: #006699; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #006699; font-weight: bold;">&lt;</span><span style="color: #006699; font-weight: bold;">tx:advice</span>&nbsp;<span style="color: red;">id</span>=<span style="color: blue;">"hiberAdvice"</span>&nbsp;<span style="color: red;">transaction-manager</span>=<span style="color: blue;">"hiberManager"</span><span style="color: #006699; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #006699; font-weight: bold;">&lt;</span><span style="color: #006699; font-weight: bold;">tx:attributes</span><span style="color: #006699; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #006699; font-weight: bold;">&lt;</span><span style="color: #006699; font-weight: bold;">tx:method</span>&nbsp;<span style="color: red;">name</span>=<span style="color: blue;">"*"</span><span style="color: #006699; font-weight: bold;">/&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #006699; font-weight: bold;">&lt;/</span><span style="color: #006699; font-weight: bold;">tx:attributes</span><span style="color: #006699; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;"><span style="color: #006699; font-weight: bold;">&lt;/</span><span style="color: #006699; font-weight: bold;">tx:advice</span><span style="color: #006699; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">&nbsp;&nbsp;</li><li style="font-size: 1em; margin-left: 38px; padding-right: 0px; border-left-width: 1px; border-left-color: #d1d7dc; line-height: 18px; background-color: #fafafa;">/beans<span style="color: #006699; font-weight: bold;">&gt;</span>&nbsp;&nbsp;</li></ol></div><br />启动Spring容器，执行UserService#logon()方法，可以查看到如下的执行日志：&nbsp;<br /><div style="font-weight: bold; padding: 5px; margin: 5px 0px 0px 15px;">引用</div><div style="border: 1px solid #cccccc; margin: 0px 5px 5px 15px; padding: 3px; background: #fafafa;">before userService.logon()..&nbsp;<br /><br /><span style="color: gray;">&#9312;在执行userService.logon()后，Spring开启一个事务</span>&nbsp;<br /><strong><span style="color: red;">Creating new transaction with name&nbsp;</span></strong>[com.baobaotao.mixdao.UserService.logon]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT&nbsp;<br />opened session at timestamp: 13009379637&nbsp;<br />Opened new Session [org.hibernate.impl.SessionImpl@c5f468] for Hibernate transaction&nbsp;<br />&#8230;&nbsp;<br />Exposing Hibernate transaction as JDBC transaction [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver]&nbsp;<br />before userService.updateLastLogonTime()..&nbsp;<br /><br /><span style="color: gray;">&#9313;userService.updateLastLogonTime()执行时自动绑定到&#9312;处开启的Session中</span>&nbsp;<br /><strong><span style="color: red;">Found thread-bound Session for HibernateTemplate</span></strong>&nbsp;<br />loading entity: [com.baobaotao.User#tom]&nbsp;<br />about to open PreparedStatement (open PreparedStatements: 0, globally: 0)&nbsp;<br />&#8230;&nbsp;<br />about to close PreparedStatement (open PreparedStatements: 1, globally: 1)&nbsp;<br />Not closing pre-bound Hibernate Session after HibernateTemplate&nbsp;<br /><strong>end updateLastLogonTime()..</strong>&nbsp;<br /><br /><strong>before scoreService.addScore()..</strong>&nbsp;<br /><br /><span style="color: gray;">&#9314;scoreService.addScore()执行时绑定到&#9312;处开启的Session中，并加入其所对应的事务中</span>&nbsp;<br /><strong><span style="color: red;">Found thread-bound Session&nbsp;</span></strong>[org.hibernate.impl.SessionImpl@c5f468] for Hibernate&nbsp;<br />transaction&nbsp;<br /><strong><span style="color: red;">Participating in existing transaction</span></strong>&nbsp;<br />&#8230;&nbsp;<br />SQL update affected 1 rows&nbsp;<br /><br /><span style="color: gray;">&#9315;此时数据源只打开了一个连接</span>&nbsp;<br /><strong><span style="color: red;">[scoreUserService.addScore]激活连接数量：1</span></strong>&nbsp;<br />end scoreService.addScore()..&nbsp;<br />Initiating transaction commit&nbsp;<br /><br /><span style="color: gray;">&#9316;提交Hibernate的事务，它将触发一级缓存到数据库的同步</span>&nbsp;<br /><strong><span style="color: red;">Committing Hibernate transaction on Session</span></strong>&nbsp;[org.hibernate.impl.SessionImpl@c5f468]&nbsp;<br />commit&nbsp;<br />processing flush-time cascades&nbsp;<br />dirty checking collections&nbsp;<br />Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects&nbsp;<br />Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections&nbsp;<br />listing entities:&nbsp;<br />com.baobaotao.User{lastLogonTime=1300937963882, score=10, userName=tom, password=123456}&nbsp;<br />re-enabling autocommit&nbsp;<br /><br /><span style="color: gray;">&#9317;提效Session底层所绑定的JDBC Connection所对应的事务</span>&nbsp;<br /><strong><span style="color: red;">committed JDBC Connection</span></strong>&nbsp;<br />transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!&nbsp;<br />Closing Hibernate Session [org.hibernate.impl.SessionImpl@c5f468] after transaction&nbsp;<br />Closing Hibernate Session&nbsp;<br />releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]&nbsp;<br />transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!&nbsp;<br />after userService.logon()..&nbsp;</div><br /><br />&nbsp;&nbsp; 仔细观察这段输出日志，在&#9312;处UserService#logon()开启一个新的事务。&#9313;处的UserService# updateLastLogonTime() 绑定到事务上下文的Session中。&#9314;处ScoreService#addScore()方法加入到&#9312;处开启的事务上下文中。&#9315;处的输出是ScoreService #addScore()方法内部的输出信息，汇报此时数据源激活的连接数为1，这清楚地告诉我们Hibernate和JDBC这两种数据访问技术在同一事务上下文中&#8220;共用&#8221;一个连接。在&#9316;处，提交Hibernate事务，接着在&#9317;处触发调用底层的Connection提交事务。&nbsp;<br />&nbsp;&nbsp; 从以上的运行结果，我们可以得出这样的结论：使用Hibernate事务管理器后，可以混合使用Hibernate和Spring JDBC数据访问技术，它们将工作于同一事务上下文中。但是使用Spring JDBC访问数据时，Hibernate的一级或二级缓存得不到同步，此外，一级缓存延迟数据同步机制可能会覆盖Spring JDBC数据更改的结果。&nbsp;<br />&nbsp;&nbsp; 由于混合数据访问技术方案存在&#8220;事务同步而缓存不同步&#8221;的情况，所以最好用Hibernate进行读写操作，而只用Spring JDBC进行读操作。如用Spring JDBC进行简要列表的查询，而用Hibernate对查询出的数据进行维护。&nbsp;<br />&nbsp;&nbsp; 如果确实要同时使用Hibernate和Spring JDBC读写数据，则必须充分考虑到Hibernate缓存机制引发的问题：必须整体分析数据维护逻辑，根据需要及时调用Hibernate的flush()方法，以免覆盖Spring JDBC的更改，在Spring JDBC更改数据库时，维护Hibernate的缓存。由于方法调用顺序的不同都可能影响数据的同步性，因此很容易发生问题，这会极大提高数据访问程序的复杂性。所以笔者郑重建议不要同时使用Spring JDBC和Hibernate对数据进行写操作。&nbsp;<br />&nbsp;&nbsp; 可以将以上结论推广到其他混合数据访问技术的方案中，如Hibernate+iBatis、JPA+Spring JDBC、JDO+Spring JDBC等。&nbsp;</div><img src ="http://www.blogjava.net/masen/aggbug/423831.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/masen/" target="_blank">Masen</a> 2015-03-25 18:07 <a href="http://www.blogjava.net/masen/articles/423831.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring声明式事务管理与配置详解(转)</title><link>http://www.blogjava.net/masen/articles/423824.html</link><dc:creator>Masen</dc:creator><author>Masen</author><pubDate>Wed, 25 Mar 2015 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/masen/articles/423824.html</guid><wfw:comment>http://www.blogjava.net/masen/comments/423824.html</wfw:comment><comments>http://www.blogjava.net/masen/articles/423824.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/masen/comments/commentRss/423824.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/masen/services/trackbacks/423824.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1、Spring声明式事务配置的五种方式　　前段时间对Spring的事务配置做了比较深入的研究，在此之前对Spring的事务配置虽说也配置过，但是一直没有一个清楚的认识。通过这次的学习发觉Spring的事务配置只要把思路理清，还是比较好掌握的。　　总结如下：　　Spring配置文件中关于事务配置总是由三个组成部分，分别是DataSource、TransactionManager和代理机制这三部分，...&nbsp;&nbsp;<a href='http://www.blogjava.net/masen/articles/423824.html'>阅读全文</a><img src ="http://www.blogjava.net/masen/aggbug/423824.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/masen/" target="_blank">Masen</a> 2015-03-25 15:48 <a href="http://www.blogjava.net/masen/articles/423824.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>cron 表达式的格式 (转http://www.blogjava.net/Unmi/archive/2008/02/23/181575.html，作者：隔叶黄莺)</title><link>http://www.blogjava.net/masen/articles/208816.html</link><dc:creator>Masen</dc:creator><author>Masen</author><pubDate>Wed, 18 Jun 2008 03:44:00 GMT</pubDate><guid>http://www.blogjava.net/masen/articles/208816.html</guid><wfw:comment>http://www.blogjava.net/masen/comments/208816.html</wfw:comment><comments>http://www.blogjava.net/masen/articles/208816.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/masen/comments/commentRss/208816.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/masen/services/trackbacks/208816.html</trackback:ping><description><![CDATA[<div class="postText"><strong>三. cron 表达式的格式</strong> <br />
<br />
Quartz cron 表达式的格式十分类似于 UNIX cron 格式，但还是有少许明显的区别。区别之一就是 Quartz 的格式向下支持到秒级别的计划，而 UNIX cron 计划仅支持至分钟级。许多我们的触发计划要基于秒级递增的(例如，每45秒)，因此这是一个非常好的差异。<br />
<br />
在 UNIX cron 里，要执行的作业（或者说命令）是存放在 cron 表达式中的，在第六个域位置上。Quartz 用 cron 表达式存放执行计划。引用了 cron 表达式的 <font color="#800080">CronTrigger</font> 在计划的时间里会与 job 关联上。<br />
<br />
另一个与 UNIX cron 表达式的不同点是在表达式中支持域的数目。UNIX 给出五个域(<font color="#800080">分、时、日、月和周</font>)，Quartz 提供七个域。表 5.1 列出了 Quartz cron 表达式支持的七个域。<br />
<br />
<strong>表 5.1. Quartz Cron 表达式支持到七个域<br />
</strong><br />
<table width="650" border="0">
    <tbody>
        <tr>
            <td><strong>名称</strong></td>
            <td><strong>是否必须</strong></td>
            <td><strong>允许值</strong></td>
            <td><strong><font color="#800080">特殊字符</font></strong></td>
        </tr>
        <tr>
            <td>秒</td>
            <td>是</td>
            <td>0-59</td>
            <td><font color="#800080">, - * /</font></td>
        </tr>
        <tr>
            <td>分</td>
            <td>是</td>
            <td>0-59</td>
            <td><font color="#800080">, - * /</font></td>
        </tr>
        <tr>
            <td>时</td>
            <td>是</td>
            <td>0-23</td>
            <td><font color="#800080">, - * /</font></td>
        </tr>
        <tr>
            <td>日</td>
            <td>是</td>
            <td>1-31</td>
            <td><font color="#800080">, - * ? / L W C</font></td>
        </tr>
        <tr>
            <td>月</td>
            <td>是</td>
            <td>1-12 或 JAN-DEC</td>
            <td><font color="#800080">, - * /</font></td>
        </tr>
        <tr>
            <td>周</td>
            <td>是</td>
            <td>1-7 或 SUN-SAT</td>
            <td><font color="#800080">, - * ? / L C #</font></td>
        </tr>
        <tr>
            <td>年</td>
            <td>否</td>
            <td>空 或 1970-2099</td>
            <td><font color="#800080">, - * /</font></td>
        </tr>
    </tbody>
</table>
<br />
月份和星期的名称是不区分大小写的。<font color="#800080">FRI</font> 和 <font color="#800080">fri</font> 是一样的。<br />
<br />
域之间有空格分隔，这和 UNIX cron 一样。无可争辩的，我们能写的最简单的表达式看起来就是这个了：<br />
<br />
<font color="#800080">* * * ? * *<br />
</font><br />
这个表达会每秒钟(每分种的、每小时的、每天的)激发一个部署的 job。<br />
<br />
<strong>&#183;理解特殊字符</strong><br />
<br />
同 UNIX cron 一样，Quartz cron 表达式支持用特殊字符来创建更为复杂的执行计划。然而，Quartz 在特殊字符的支持上比标准 UNIX cron 表达式更丰富了。<br />
<br />
<strong><font color="#800080">* </font>星号</strong><br />
<br />
使用星号(*) 指示着你想在这个域上包含所有合法的值。例如，在月份域上使用星号意味着每个月都会触发这个 trigger。<br />
<br />
表达式样例：<br />
<br />
<font color="#800080">0 * 17 * * ?<br />
</font><br />
意义：每天从下午5点到下午5:59中的每分钟激发一次 trigger。它停在下午 5:59 是因为值 17 在小时域上，在下午 6 点时，小时变为 18 了，也就不再理会这个 trigger，直到下一天的下午5点。<br />
<br />
在你希望 trigger 在该域的所有有效值上被激发时使用 <font color="#800080">*</font> 字符。<br />
<br />
<strong><font color="#800080">? </font>问号</strong><br />
<br />
<font color="#800080">?</font> 号只能用在<font color="#800080">日</font>和<font color="#800080">周域</font>上，但是不能在这两个域上同时使用。你可以认为 <font color="#800080">?</font> 字符是 "我并不关心在该域上是什么值。" 这不同于星号，星号是指示着该域上的每一个值。? 是说不为该域指定值。<br />
<br />
不能同时这两个域上指定值的理由是难以解释甚至是难以理解的。基本上，假定同时指定值的话，意义就会变得含混不清了：考虑一下，如果一个表达式在<font color="#800080">日</font>域上有值11，同时在<font color="#800080">周</font>域上指定了 <font color="#800080">WED</font>。那么是要 trigger 仅在每个月的11号，且正好又是星期三那天被激发？还是在每个星期三的11号被激发呢？要去除这种不明确性的办法就是不能同时在这两个域上指定值。<br />
<br />
只要记住，假如你为这两域的其中一个指定了值，那就必须在另一个字值上放一个 <font color="#800080">?</font>。<br />
<br />
表达式样例：<br />
<br />
<font color="#800080">0 10,44 14 ? 3 WEB</font><br />
<br />
意义：在三月中的每个星期三的下午 2:10 和 下午 2:44 被触发。<br />
<br />
<strong><font color="#800080">,</font> 逗号</strong><br />
<br />
逗号 (<font color="#800080">,</font>) 是用来在给某个域上指定一个值列表的。例如，使用值 0,15,30,45 在秒域上意味着每15秒触发一个 trigger。<br />
<br />
表达式样例：<br />
<br />
<font color="#800080">0 0,15,30,45 * * * ?</font><br />
<br />
意义：每刻钟触发一次 trigger。<br />
<br />
<strong><font color="#800080">/</font> 斜杠</strong><br />
<br />
斜杠 (<font color="#800080">/</font>) 是用于时间表的递增的。我们刚刚用了逗号来表示每15分钟的递增，但是我们也能写成这样 <font color="#800080">0/15</font>。<br />
<br />
表达式样例：<br />
<br />
<font color="#800080">0/15 0/30 * * * ?<br />
</font><br />
意义：在整点和半点时每15秒触发 trigger。<br />
<br />
<strong>- 中划线</strong><br />
<br />
中划线 (<font color="#800080">-</font>) 用于指定一个范围。例如，在小时域上的 3-8 意味着 "3,4,5,6,7 和 8 点。"&nbsp; 域的值不允许回卷，所以像 50-10 这样的值是不允许的。<br />
<br />
表达式样例：<br />
<br />
<font color="#800080">0 45 3-8 ? * *<br />
</font><br />
意义：在上午的3点至上午的8点的45分时触发 trigger。<br />
<br />
<strong><font color="#800080">L</font> 字母<br />
</strong><br />
<font color="#800080">L</font> 说明了某域上允许的最后一个值。它仅被<font color="#800080">日</font>和<font color="#800080">周</font>域支持。当用在日域上，表示的是在<font color="#800080">月</font>域上指定的月份的最后一天。例如，当月域上指定了 <font color="#800080">JAN</font> 时，在<font color="#800080">日</font>域上的 <font color="#800080">L</font> 会促使 trigger 在1月31号被触发。假如<font color="#800080">月</font>域上是 <font color="#800080">SEP</font>，那么 L 会预示着在9月30号触发。换句话说，就是不管指定了哪个月，都是在相应月份的时最后一天触发 trigger。<br />
<br />
表达式 <font color="#800080">0 0 8 L * ?</font> 意义是在每个月最后一天的上午 8:00 触发 trigger。在<font color="#800080">月</font>域上的 * 说明是 "每个月"。<br />
<br />
当 <font color="#800080">L</font> 字母用于周域上，指示着周的最后一天，就是星期六 (或者数字7)。所以如果你需要在每个月的最后一个星期六下午的 11:59 触发 trigger，你可以用这样的表达式 <font color="#800080">0 59 23 ? * L</font>。<br />
<br />
当使用于<font color="#800080">周</font>域上，你可以用一个数字与 <font color="#800080">L</font> 连起来表示月份的最后一个星期 X。例如，表达式 <font color="#800080">0 0 12 ? * 2L</font> 说的是在每个月的最后一个星期一触发 trigger。<br />
<br />
<table style="border-right: 1px; border-top: 1px; border-left: 1px; border-bottom: 1px" width="650" align="center" border="1">
    <tbody>
        <tr>
            <td><strong>不要让范围和列表值与 L 连用</strong><br />
            <br />
            虽然你能用星期数(<font color="#800080">1-7</font>)与 L 连用，但是不允许你用一个范围值和列表值与 L 连用。这会产生不可预知的结果。</td>
        </tr>
    </tbody>
</table>
<br />
<strong><font color="#800080">W</font> 字母</strong><br />
<br />
<font color="#800080">W</font> 字符代表着平日 (<font color="#800080">Mon-Fri</font>)，并且仅能用于日域中。它用来指定离指定日的最近的一个平日。大部分的商业处理都是基于工作周的，所以 W 字符可能是非常重要的。例如，日域中的 <font color="#800080">15W</font> 意味着 "离该月15号的最近一个平日。" 假如15号是星期六，那么 trigger 会在14号(星期四)触发，因为距15号最近的是星期一，这个例子中也会是17号<font color="#0000ff">（译者Unmi注：不会在17号触发的，如果是<font color="#800080">15W</font>，可能会是在14号(15号是星期六)或者15号(15号是星期天)触发，也就是只能出现在邻近的一天，如果15号当天为平日直接就会当日执行）</font>。<font color="#800080">W</font> 只能用在指定的<font color="#800080">日</font>域为单天，不能是范围或列表值。<br />
<br />
<strong><font color="#800080">#</font> 井号</strong><br />
<br />
<font color="#800080">#</font> 字符仅能用于<font color="#800080">周</font>域中。它用于指定月份中的第几周的哪一天。例如，如果你指定周域的值为 <font color="#800080">6#3</font>，它意思是某月的第三个周五 (<font color="#800080">6</font>=星期五，<font color="#800080">#3</font>意味着月份中的第三周)。另一个例子 <font color="#800080">2#1</font> 意思是某月的第一个星期一 (<font color="#800080">2</font>=星期一，<font color="#800080">#1</font>意味着月份中的第一周)。注意，假如你指定 <font color="#800080">#5</font>，然而月份中没有第 5 周，那么该月不会触发。<br />
<br />
<br />
<font color="#ff0000"><strong>
<hr />
[版权声明]</strong>本站内文章，如未标注 [转载]，均系原创或翻译之作，本人 Unmi 保留一切权利。本站原创及译作未经本人许可，不得用于商业用途及传统媒体。网络媒体可随意转载，或以此为基础进行演译，但务必以链接形式注明原始出处和作者信息，否则属于侵权行为。另对本站转载他处文章，俱有说明，如有侵权请联系本人，本人将会在第一时间删除侵权文章。及此说明，重之之重。</font> </div>
<img src ="http://www.blogjava.net/masen/aggbug/208816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/masen/" target="_blank">Masen</a> 2008-06-18 11:44 <a href="http://www.blogjava.net/masen/articles/208816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>详解spring事务属性(转)</title><link>http://www.blogjava.net/masen/articles/208548.html</link><dc:creator>Masen</dc:creator><author>Masen</author><pubDate>Tue, 17 Jun 2008 03:02:00 GMT</pubDate><guid>http://www.blogjava.net/masen/articles/208548.html</guid><wfw:comment>http://www.blogjava.net/masen/comments/208548.html</wfw:comment><comments>http://www.blogjava.net/masen/articles/208548.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/masen/comments/commentRss/208548.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/masen/services/trackbacks/208548.html</trackback:ping><description><![CDATA[<p>Spring声明式事务让我们从复杂的事务处理中得到解脱。使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要我们在与事务相关的方法中处理大量的try&#8230;catch&#8230;finally代码。 <br />
我们在使用Spring声明式事务时，有一个非常重要的概念就是事务属性。事务属性通常由事务的传播行为，事务的隔离级别，事务的超时值和事务只读标志组成。我们在进行事务划分时，需要进行事务定义，也就是配置事务的属性。 <br />
Spring在<strong>TransactionDefinition</strong>接口中定义这些属性,以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事务管理的核心接口。 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>TransactionDefinition&nbsp;&nbsp;&nbsp;</span></span>
    <li><span class="keyword">public</span><span> </span><span class="keyword">interface</span><span> TransactionDefinition {&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span> getPropagationBehavior();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span> getIsolationLevel();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span> getTimeout();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">boolean</span><span> isReadOnly();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<p>&nbsp;</p>
<p>getTimeout()方法，它返回事务必须在多少秒内完成。 <br />
isReadOnly(),事务是否只读，事务管理器能够根据这个返回值进行优化，确保事务是只读的。 <br />
getIsolationLevel()方法返回事务的隔离级别，事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据。</p>
<p>在TransactionDefinition接口中定义了五个不同的事务隔离级别 <br />
<strong>ISOLATION_DEFAULT </strong>这是一个PlatfromTransactionManager默认的隔离级别，使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应 <br />
<strong>ISOLATION_READ_UNCOMMITTED</strong> 这是事务最低的隔离级别，它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读，不可重复读和幻像读。 <br />
例如: <br />
Mary的原工资为1000,财务人员将Mary的工资改为了8000，但未提交事务 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>Connection con1 = getConnection();&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>con.setAutoCommit(</span><span class="keyword">false</span><span>);&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>update employee set salary = </span><span class="number">8000</span><span> where empId =</span><span class="string">"Mary"</span><span>;&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
与此同时，Mary正在读取自己的工资 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>Connection con2 = getConnection();&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>select&nbsp;&nbsp; salary from employee where empId =</span><span class="string">"Mary"</span><span>;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>con2.commit();&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<p>&nbsp;</p>
<p>Mary发现自己的工资变为了8000，欢天喜地！ <br />
而财务发现操作有误，而回滚了事务,Mary的工资又变为了1000 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//con1 </span><span>&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp; con1.rollback();&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
像这样,Mary记取的工资数8000是一个脏数据。
<p>&nbsp;</p>
<p><strong>ISOLATION_READ_COMMITTED </strong>保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现，但是可能会出现不可重复读和幻像读。</p>
<p><strong>ISOLATION_REPEATABLE_READ </strong>这种事务隔离级别可以防止脏读，不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外，还保证了避免下面的情况产生(不可重复读)。</p>
<p>在事务1中，Mary 读取了自己的工资为1000,操作并没有完成 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con1 = getConnection();&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>select salary from employee empId =</span><span class="string">"Mary"</span><span>;&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<p>&nbsp;</p>
<p>在事务2中，这时财务人员修改了Mary的工资为2000,并提交了事务. <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con2 = getConnection();&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>update employee set salary = </span><span class="number">2000</span><span>;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>con2.commit();&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<p>&nbsp;</p>
<p>在事务1中，Mary 再次读取自己的工资时，工资变为了2000 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//con1 </span><span>&nbsp;&nbsp;</span></span>
    <li><span>select salary from employee empId =</span><span class="string">"Mary"</span><span>;&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<p>&nbsp;</p>
<p>在一个事务中前后两次读取的结果并不致，导致了不可重复读。 <br />
使用ISOLATION_REPEATABLE_READ可以避免这种情况发生。</p>
<p><strong>ISOLATION_SERIALIZABLE </strong>这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读，不可重复读外，还避免了幻像读。</p>
<p>目前工资为1000的员工有10人。 <br />
事务1,读取所有工资为1000的员工。 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con1 = getConnection();&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>Select * from employee where salary =</span><span class="number">1000</span><span>;&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
共读取10条记录
<p>&nbsp;</p>
<p>这时另一个事务向employee表插入了一条员工记录，工资也为1000 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con2 = getConnection();&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>Insert into employee(empId,salary) values(</span><span class="string">"Lili"</span><span>,</span><span class="number">1000</span><span>);&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>con2.commit();&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<p>&nbsp;</p>
<p>事务1再次读取所有工资为1000的员工 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//con1 </span><span>&nbsp;&nbsp;</span></span>
    <li><span>select * from employee where salary =</span><span class="number">1000</span><span>;&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<p>&nbsp;</p>
<p>共读取到了11条记录，这就产生了幻像读。 <br />
ISOLATION_SERIALIZABLE能避免这样的情况发生。但是这样也耗费了最大的资源。</p>
<p><strong>getPropagationBehavior()</strong>返回事务的传播行为，由是否有一个活动的事务来决定一个事务调用。</p>
<p><strong>在TransactionDefinition接口中定义了七个事务传播行为</strong>。</p>
<p><strong>PROPAGATION_REQUIRED </strong>如果存在一个事务，则支持当前事务。如果没有事务则开启一个新的事务。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性 PROPAGATION_REQUIRED </span><span>&nbsp;&nbsp;</span></span>
    <li><span>methodA{&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&#8230;&#8230;&nbsp;&nbsp;&nbsp;</span>
    <li><span>methodB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&#8230;&#8230;&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span class="comment">//事务属性 PROPAGATION_REQUIRED </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>methodB{&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; &#8230;&#8230;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
使用spring声明式事务，spring使用AOP来支持声明式事务，会根据事务属性，自动在方法调用之前决定是否开启一个事务，并在方法执行之后决定事务提交或回滚事务。
<p>&nbsp;</p>
<p>单独调用methodB方法 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>main{&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp; metodB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
相当于 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>Main{&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>Connection con=</span><span class="keyword">null</span><span>;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; rry{&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; con = getConnection();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; con.setAutoCommit(</span><span class="keyword">false</span><span>);&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span class="comment">//方法调用 </span><span>&nbsp;&nbsp;</span>
    <li><span>methodB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span class="comment">//提交事务 </span><span>&nbsp;&nbsp;</span>
    <li><span>con.commit();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span>
    <li><span>Catch(RuntimeException ex){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="comment">//回滚事务 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; con.rollback();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span>
    <li><span class="keyword">finally</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; closeCon();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
Spring保证在methodB方法中所有的调用都获得到一个相同的连接。在调用methodB时，没有一个存在的事务，所以获得一个新的连接，开启了一个新的事务。
<p>&nbsp;</p>
<p>单独调用MethodA时，在MethodA内又会调用MethodB.</p>
<p>执行效果相当于 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main{&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp;&nbsp; Connection con = </span><span class="keyword">null</span><span>;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; con = getConnection();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; methodA();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; con.commit();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span>
    <li><span>cathc(RuntimeException ex){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>con.rollback();&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">finally</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; closeCon();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
调用MethodA时，环境中没有事务，所以开启一个新的事务. <br />
当在MethodA中调用MethodB时，环境中已经有了一个事务，所以methodB就加入当前事务。
<p>&nbsp;</p>
<p><strong>PROPAGATION_SUPPORTS </strong>如果存在一个事务，支持当前事务。如果没有事务，则非事务的执行。但是对于事务同步的事务管理器，PROPAGATION_SUPPORTS与不使用事务有少许不同。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性 PROPAGATION_REQUIRED&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span>
    <li><span>methodA(){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; methodB();&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span class="comment">//事务属性 PROPAGATION_SUPPORTS&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>methodB(){&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; &#8230;&#8230;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
单纯的调用methodB时，methodB方法是非事务的执行的。 <br />
当调用methdA时,methodB则加入了methodA的事务中,事务地执行。
<p>&nbsp;</p>
<p>PROPAGATION_MANDATORY 如果已经存在一个事务，支持当前事务。如果没有一个活动的事务，则抛出异常。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性 PROPAGATION_REQUIRED&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span>
    <li><span>methodA(){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; methodB();&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span class="comment">//事务属性 PROPAGATION_MANDATORY&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>methodB(){&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; &#8230;&#8230;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
当单独调用methodB时，因为当前没有一个活动的事务，则会抛出异常 <br />
throw new IllegalTransactionStateException("Transaction propagation 'mandatory' but no existing transaction found");
<p>&nbsp;</p>
<p>当调用methodA时，methodB则加入到methodA的事务中，事务地执行。</p>
<p><strong>PROPAGATION_REQUIRES_NEW </strong>总是开启一个新的事务。如果一个事务已经存在，则将这个存在的事务挂起。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性 PROPAGATION_REQUIRED&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span>
    <li><span>methodA(){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; doSomeThingA();&nbsp;&nbsp;&nbsp;</span>
    <li><span>methodB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>doSomeThingB();&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span class="comment">//事务属性 PROPAGATION_REQUIRES_NEW&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>methodB(){&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; &#8230;&#8230;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
当单独调用methodB时，相当于把methodb声明为REQUIRED。开启一个新的事务，事务地执行。
<p>&nbsp;</p>
<p>当调用methodA时 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>main(){&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>&nbsp;&nbsp; methodA();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
情况有些大不一样.相当于下面的效果。 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main(){&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>TransactionManager tm = </span><span class="keyword">null</span><span>;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">try</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span><span class="comment">//获得一个JTA事务管理器 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp; tm = getTransactionManager();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; tm.begin();</span><span class="comment">//开启一个新的事务 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp; Transaction ts1 = tm.getTransaction();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; doSomeThing();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp; tm.suspend();</span><span class="comment">//挂起当前事务 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tm.begin();</span><span class="comment">//重新开启第二个事务 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Transaction ts2 = tm.getTransaction();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; methodB();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ts2.commit();</span><span class="comment">//提交第二个事务 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; Catch(RunTimeException ex){&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ts2.rollback();</span><span class="comment">//回滚第二个事务 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span><span class="keyword">finally</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="comment">//methodB执行完后，复恢第一个事务 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; tm.resume(ts1);&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>doSomeThingB();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; ts1.commit();</span><span class="comment">//提交第一个事务 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span>
    <li><span class="keyword">catch</span><span>(RunTimeException ex){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; ts1.rollback();</span><span class="comment">//回滚第一个事务 </span><span>&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">finally</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
在这里，我把ts1称为外层事务，ts2称为内层事务。从上面的代码可以看出，ts2与ts1是两个独立的事务，互不相干。Ts2是否成功并不依赖于ts1。如果methodA方法在调用methodB方法后的doSomeThingB方法失败了，而methodB方法所做的结果依然被提交。而除了methodB之外的其它代码导致的结果却被回滚了。 <br />
使用PROPAGATION_REQUIRES_NEW,需要使用JtaTransactionManager作为事务管理器。
<p>&nbsp;</p>
<p><strong>PROPAGATION_NOT_SUPPORTED</strong> 总是非事务地执行，并挂起任何存在的事务。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性 PROPAGATION_REQUIRED&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span>
    <li><span>methodA(){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; doSomeThingA();&nbsp;&nbsp;&nbsp;</span>
    <li><span>methodB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>doSomeThingB();&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span class="comment">//事务属性 PROPAGATION_NOT_SUPPORTED&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>methodB(){&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; &#8230;&#8230;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
当单独调用methodB时，不启用任何事务机制，非事务地执行。 <br />
当调用methodA时，相当于下面的效果
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main(){&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>TransactionManager tm = </span><span class="keyword">null</span><span>;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">try</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span><span class="comment">//获得一个JTA事务管理器 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp; tm = getTransactionManager();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; tm.begin();</span><span class="comment">//开启一个新的事务 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp; Transaction ts1 = tm.getTransaction();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; doSomeThing();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp; tm.suspend();</span><span class="comment">//挂起当前事务 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; methodB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="comment">//methodB执行完后，复恢第一个事务 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; tm.resume(ts1);&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>doSomeThingB();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp; ts1.commit();</span><span class="comment">//提交第一个事务 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span>
    <li><span class="keyword">catch</span><span>(RunTimeException ex){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; ts1.rollback();</span><span class="comment">//回滚第一个事务 </span><span>&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">finally</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作为事务管理器。
<p>&nbsp;</p>
<p><strong>PROPAGATION_NEVER</strong> 总是非事务地执行，如果存在一个活动事务，则抛出异常</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性 PROPAGATION_REQUIRED&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span>
    <li><span>methodA(){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; doSomeThingA();&nbsp;&nbsp;&nbsp;</span>
    <li><span>methodB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>doSomeThingB();&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span class="comment">//事务属性 PROPAGATION_NEVER&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>methodB(){&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; &#8230;&#8230;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
单独调用methodB，则非事务的执行。 <br />
调用methodA则会抛出异常 <br />
throw new IllegalTransactionStateException( <br />
"Transaction propagation 'never' but existing transaction found");
<p>&nbsp;</p>
<p><strong>PROPAGATION_NESTED</strong>如果一个活动的事务存在，则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行</p>
<p>这是一个嵌套事务,使用JDBC 3.0驱动时,仅仅支持DataSourceTransactionManager作为事务管理器。需要JDBC 驱动的java.sql.Savepoint类。有一些JTA的事务管理器实现可能也提供了同样的功能。</p>
<p>使用PROPAGATION_NESTED，还需要把PlatformTransactionManager的nestedTransactionAllowed属性设为true; <br />
而nestedTransactionAllowed属性值默认为false; <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性 PROPAGATION_REQUIRED&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span>
    <li><span>methodA(){&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; doSomeThingA();&nbsp;&nbsp;&nbsp;</span>
    <li><span>methodB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>doSomeThingB();&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span class="comment">//事务属性 PROPAGATION_NESTED </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>methodB(){&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; &#8230;&#8230;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<br />
如果单独调用methodB方法，则按REQUIRED属性执行。
<p>&nbsp;</p>
<p>如果调用methodA方法，相当于下面的效果 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main(){&nbsp;&nbsp;&nbsp;</span></span>
    <li><span>Connection con = </span><span class="keyword">null</span><span>;&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>Savepoint savepoint = </span><span class="keyword">null</span><span>;&nbsp;&nbsp;&nbsp;</span>
    <li><span class="keyword">try</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; con = getConnection();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; con.setAutoCommit(</span><span class="keyword">false</span><span>);&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; doSomeThingA();&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; savepoint = con2.setSavepoint();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; methodB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; }</span><span class="keyword">catch</span><span>(RuntimeException ex){&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; con.rollback(savepoint);&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp;</span><span class="keyword">finally</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; doSomeThingB();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp; con.commit();&nbsp;&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">catch</span><span>(RuntimeException ex){&nbsp;&nbsp;&nbsp;</span>
    <li><span>&nbsp;&nbsp; con.rollback();&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;</span>
    <li><span class="keyword">finally</span><span>{&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span>
    <li><span>}&nbsp;&nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
当methodB方法调用之前，调用setSavepoint方法，保存当前的状态到savepoint。如果methodB方法调用失败，则恢复到之前保存的状态。但是需要注意的是，这时的事务并没有进行提交，如果后续的代码(doSomeThingB()方法)调用失败，则回滚包括methodB方法的所有操作。
<p>&nbsp;</p>
<p><strong>嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时，会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚</strong>。</p>
<p><strong>PROPAGATION_NESTED 与PROPAGATION_REQUIRES_NEW的区别</strong>:它们非常类似,都像一个嵌套事务，如果不存在一个活动的事务，都会开启一个新的事务。使用PROPAGATION_REQUIRES_NEW时，内层事务与外层事务就像两个独立的事务一样，一旦内层事务进行了提交后，外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA事务管理器的支持。 <br />
使用PROPAGATION_NESTED时，外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚，它是一个真正的嵌套事务。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTED时，需要JDBC 3.0以上驱动及1.4以上的JDK版本支持。其它的JTA TrasactionManager实现可能有不同的支持方式。</p>
<p>PROPAGATION_REQUIRED应该是我们首先的事务传播行为。它能够满足我们大多数的事务需求。</p>
<img src ="http://www.blogjava.net/masen/aggbug/208548.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/masen/" target="_blank">Masen</a> 2008-06-17 11:02 <a href="http://www.blogjava.net/masen/articles/208548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring事务相关（转）</title><link>http://www.blogjava.net/masen/articles/206269.html</link><dc:creator>Masen</dc:creator><author>Masen</author><pubDate>Fri, 06 Jun 2008 03:12:00 GMT</pubDate><guid>http://www.blogjava.net/masen/articles/206269.html</guid><wfw:comment>http://www.blogjava.net/masen/comments/206269.html</wfw:comment><comments>http://www.blogjava.net/masen/articles/206269.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/masen/comments/commentRss/206269.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/masen/services/trackbacks/206269.html</trackback:ping><description><![CDATA[<h1 class="block_title"><a id="viewpost1_TitleUrl" href="http://www.blogjava.net/baoyaer/articles/93060.html">spring事务管理</a></h1>
<div class="post">
<div class="postcontent">通常通过TransactionProxyFactoryBean设置Spring事务代理。我们需要一个目标对象包装在事务代理中。这个目标对象一般是一个普通Java对象的bean。当我们定义TransactionProxyFactoryBean时，必须提供一个相关的 PlatformTransactionManager的引用和<strong>事务属性</strong>。 <strong>事务属性</strong>含有上面描述的事务定义。
<pre>&lt;bean id="petStore" <br />
&nbsp;&nbsp;&nbsp;&nbsp;class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="transactionManager"&gt;&lt;ref bean="transactionManager"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="target"&gt;&lt;ref bean="petStoreTarget"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="transactionAttributes"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="insert*"&gt;PROPAGATION_REQUIRED,-MyCheckedException&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="update*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;<br />
&lt;/bean&gt;</pre>
<p>事务代理会实现目标对象的接口：这里是id为petStoreTarget的bean。（使用 CGLIB也可以实现具体类的代理。只要设置proxyTargetClass属性为true就可以。如果目标对象没有实现任何接口，这将自动设置该属性为true。通常，我们希望面向接口而不是类编程。）使用proxyInterfaces属性来限定事务代理来代 理指定接口也是可以的<img alt="" src="http://blog.csdn.net/fckeditor/editor/images/smiley/msn/angry_smile.gif" />（一般来说是个好想法）。也可以通过从 <tt><font face="新宋体">org.springframework.aop.framework.ProxyConfig</font></tt>继承或所有AOP代理工厂共享 的属性来定制TransactionProxyFactoryBean的行为。 </p>
<p>这里的transactionAttributes属性定义在 <tt><font face="新宋体">org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource</font></tt> 中的属性格式来设置。这个包括通配符的方法名称映射是很直观的。注意 insert*的映射的值包括回滚规则。添加的<tt><font face="新宋体">-MyCheckedException</font></tt> 指定如果方法抛出<tt><font face="新宋体">MyCheckedException</font></tt>或它的子类，事务将 会自动回滚。可以用逗号分隔定义多个回滚规则。<font color="#ff0000"><strong>-前缀强制回滚，+前缀指定提交</strong></font>（这允许即使抛出unchecked异常时也可以提交事务，当然你自己要明白自己 在做什么）。</p>
<p><tt><font face="新宋体">TransactionProxyFactoryBean</font></tt>允许你通过 &#8220;preInterceptors&#8221;和&#8220;postInterceptors&#8221;属性设置&#8220;前&#8221;或&#8220;后&#8221;通知来提供额外的 拦截行为。可以设置任意数量的&#8220;前&#8221;和&#8220;后&#8221;通知，它们的类型可以是 <tt><font face="新宋体">Advisor</font></tt>（可以包含一个切入点）， <tt><font face="新宋体">MethodInterceptor</font></tt>或被当前Spring配置支持的通知类型 （例如<tt><font face="新宋体">ThrowAdvice</font></tt>， <tt><font face="新宋体">AfterReturningtAdvice</font></tt>或<tt><font face="新宋体">BeforeAdvice</font></tt>， 这些都是默认支持的）。这些通知必须支持实例共享模式。如果你需要高级AOP特 性来使用事务，如有状态的maxin，那最好使用通用的 <tt><font face="新宋体">org.springframework.aop.framework.ProxyFactoryBean</font></tt>， 而不是<tt><font face="新宋体">TransactionProxyFactoryBean</font></tt>实用代理创建者。</p>
<p>也可以设置自动代理：配置AOP框架，不需要单独的代理定义类就可以生成类的 代理。</p>
<p>附两个spring的事务配置例子：<br />
&lt;prop key="add"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; PROPAGATION_REQUIRES_NEW, -MyException <br />
&lt;/prop&gt;<br />
注：上面的意思是add方法将独占一个事务，当事务处理过程中产生MyException异常或者该异常的子类将回滚该事务。<br />
<br />
&lt;prop key="loadAll"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;PROPAGATION_SUPPORTS, ISOLATION_READ_COMMITED, Readonly<br />
&lt;/prop&gt;<br />
注：表示loadAll方法支持事务，而且不会读取没有提交事务的数据。它的数据为只读（这样有助于提高读取的性能）<br />
<br />
附A Spring中的所有事务策略<br />
<br />
PROPAGATION_MANDATORY<br />
PROPAGATION_NESTED <br />
PROPAGATION_NEVER <br />
PROPAGATION_NOT_SUPPORTED<br />
PROPAGATION_REQUIRED<br />
PROPAGATION_REQUIRED_NEW<br />
PROPAGATION_SUPPORTS<br />
<br />
附B Spring中所有的隔离策略：<br />
<br />
ISOLATION_DEFAULT<br />
ISOLATION_READ_UNCOMMITED<br />
ISOLATION_COMMITED<br />
ISOLATION_REPEATABLE_READ<br />
ISOLATION_SERIALIZABLE </p>
<p><a href="http://www.blogjava.net/DenisLing/archive/2005/12/18/spring.html" target="_blank"><font color="#000000" size="6"><strong>Spring事务类型祥解</strong></font></a><font size="6"><strong></strong></font></p>
<p>大家可能在spring中经常看到这样的定义：</p>
<p>&nbsp;</p>
<p>&lt;prop key="load*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;&lt;prop key="store*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;</p>
<p>估计有好多朋友还没有弄清楚里面的值的意思，仔细看完下面应该知道自己什么情况下面应该使用什么样的声明。^_^<br />
</p>
<p>&nbsp;</p>
<p>Spring中常用事务类型：<br />
</p>
<ul>
    <li>PROPAGATION_REQUIRED--支持当前事务，如果当前没有事务，就新建一个事务。这是最常见的选择。 <br />
    <li>PROPAGATION_SUPPORTS--支持当前事务，如果当前没有事务，就以非事务方式执行。 <br />
    <li>PROPAGATION_MANDATORY--支持当前事务，如果当前没有事务，就抛出异常。 <br />
    <li>PROPAGATION_REQUIRES_NEW--新建事务，如果当前存在事务，把当前事务挂起。 <br />
    <li>PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作，如果当前存在事务，就把当前事务挂起。 <br />
    <li>PROPAGATION_NEVER--以非事务方式执行，如果当前存在事务，则抛出异常。 <br />
    <li>PROPAGATION_NESTED--如果当前存在事务，则在嵌套事务内执行。如果当前没有事务，则进行与PROPAGATION_REQUIRED类似的操作。<br />
    </li>
</ul>
<div id="articleview_summary">摘要：<br />
Spring和EJB一样，提供了两种事务管理方式：编程式和声明式。在考试系统中我们将使用声明式的事务管理，这是spring推荐的做法。使用这种方式可以体验到spring的强大便捷，而且我们无须在Dao类中编写任何特殊的代码，只需要通过配置文件就可以让普通的java类加载到事务管理中，这个意义是很重大的。 <br />
<br />
<br />
本文Matrix永久镜像：<a href="http://www.matrix.org.cn/resource/article/1/1339.html">http://www.matrix.org.cn/resource/article/1/1339.html</a><br />
说明：本文可能由Matrix原创，也可能由Matrix的会员整理，或者由<br />
Matrix的Crawler在全球知名Java或者其他技术相关站点抓取并永久<br />
保留镜像，Matrix会保留所有原来的出处URL，并在显著地方作出说明，<br />
如果你发觉出处URL有误，请联系Matrix改正.<br />
</div>
<div id="divarticlecontent">四、Spring中的事务控制<br />
<br />
Spring和EJB一样，提供了两种事务管理方式：编程式和声明式。在考试系统中我们将使用声明式的事务管理，这是spring推荐的做法。使用这种方式可以体验到spring的强大便捷，而且我们无须在Dao类中编写任何特殊的代码，只需要通过配置文件就可以让普通的java类加载到事务管理中，这个意义是很重大的。<br />
<br />
Spring中进行事务管理的通常方式是利用AOP（面向切片编程）的方式，为普通java类封装事务控制，它是通过动态代理实现的，由于接口是延迟实例化的，spring在这段时间内通过拦截器，加载事务切片。原理就是这样，具体细节请参考jdk中有关动态代理的文档。本文主要讲解如何在spring中进行事务控制。<br />
<br />
动态代理的一个重要特征是，它是针对接口的，所以我们的dao要通过动态代理来让spring接管事务，就必须在dao前面抽象出一个接口，当然如果没有这样的接口，那么spring会使用CGLIB来解决问题，但这不是spring推荐的方式，我们也不做讨论。<br />
<br />
参照前面的例子，我们为StudentManager.java定义一个接口，它的内容如下：<br />
<br />
<pre class="overflow" title="pre code">/*<br />
* 创建日期 2005-3-25<br />
*/<br />
package org.bromon.spring.examer.student;<br />
<br />
import java.util.List;<br />
<br />
import org.bromon.spring.examer.pojo.Student;<br />
<br />
/**<br />
* @author Bromon<br />
*/<br />
public interface StudentManagerInterface<br />
{<br />
&nbsp; &nbsp; public void add(Student s);<br />
&nbsp; &nbsp; public void del(Student s);<br />
&nbsp; &nbsp; public void update(Student s);<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; public List loadAll();<br />
&nbsp; &nbsp; public Student loadById(int id);<br />
}</pre>
<br />
StudentManager也应该做出修改，实现该接口：<br />
<br />
<pre class="overflow" title="pre code">public class StudentManager extends HibernateDaoSupport implements StudentManagerInterface</pre>
<br />
现在需要修改配置文件，用于定义Hibrenate适用的事务管理器，并且把sessionFactory注入进去，同时还需要通过注册一个DefaultTransactionAttribute对象，来指出事务策略。其中sessionFactory的定义已经在本文的第三章中说明。<br />
<br />
首先定义一个Hibernate的事务管理器，让它来管理sessionFactory：<br />
<pre class="overflow" title="pre code">&lt;bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;property name="sessionFactory"&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&lt;ref bean="sessionFactory"/&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;/property&gt;<br />
&lt;/bean&gt;</pre>
<br />
下面定义事务管理策略，我们希望把策略定义在方法这个级别上，提供最大的灵活性，本例中将add方法定义为：PROPAGATION_REQUIRES_NEW，这可以保证它将始终运行在一个事务中。<br />
<br />
<pre class="overflow" title="pre code">&lt;bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;property name="properties"&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&lt;props&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&lt;prop key="add"&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;PROPAGATION_REQUIRES_NEW<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&lt;/prop&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&lt;/props&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;/property&gt;<br />
&nbsp; &nbsp;&lt;/bean&gt;</pre>
<br />
我们不仅可以为add方法定义事务策略,还可以定义事务隔离程度和回滚策略,他们以逗号隔开,比如我们的add事务可以定义为:<br />
<br />
<pre class="overflow" title="pre code">&lt;prop key="add"&gt;<br />
&nbsp; &nbsp;PROPAGATION_REQUIRES_NEW,-ExamerException<br />
&lt;/prop</pre>
&gt;<br />
<br />
这个事务策略表示add方法将会独占一个事务，当事务过程中产生ExamerException异常，事务会回滚。<br />
<br />
Add/update/del都是写入方法，对于select（读取）方法，我们可以指定较为复杂的事务策略，比如对于loadAll()方法：<br />
<br />
<pre class="overflow" title="pre code">&lt;prop key=&#8221;loadAll&#8221;&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly<br />
&nbsp; &nbsp;&lt;/prop&gt;</pre>
<br />
<br />
该事务的含义为，loadAll方法支持事务，不会读去位提交的数据，它的数据为只读（可提高执行速度）。<br />
<br />
如你所见，我们的StudentManagerInterface接口中还有一个loadById(int id)方法，也许我们将来还会有很多的loadByXXXX的方法，难道要意义为他们指定事务策略？太烦人了，他们应该和loadAll()一样，所以我们可以使用通配符，定义所有的loadXXXX方法：<br />
<br />
<pre class="overflow" title="pre code">&lt;prop key=&#8221;load*&#8221;&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly<br />
&nbsp; &nbsp;&lt;/prop&gt;</pre>
<br />
<br />
现在可以定义事务管理器：<br />
<pre class="overflow" title="pre code">&lt;bean id="studentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;property name="target"&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&lt;ref bean="studentManager"/&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;/property&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;property name="transactionManager"&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&lt;ref bean="transactionManager"/&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;/property&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;property name="transactionAttributeSource"&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&lt;ref bean="transactionAttributeSource"/&gt;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&lt;/property&gt;<br />
&lt;/bean&gt;</pre>
<br />
<br />
这个bean的外观是一个接口(StudentManagerInterface)，我们指出了它的具体实现(studentManager)，而且为它绑定了事务策略。在客户端使用的时候，获得对象是StudentManagerInterface，所有的操作都是针对这个接口的。测试代码并没有改变，我们虽然修改了很多地方，加入了事务控制，但是客户端并没有受到影响，这也体现了spring的一些优势。测试代码如下：<br />
<br />
<pre class="overflow" title="pre code">public void testAdd() <br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");<br />
&nbsp; &nbsp; &nbsp; &nbsp; StudentManager sm=(StudentManager)ctx.getBean("studentManager");<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; Student s=new Student();<br />
&nbsp; &nbsp; &nbsp; &nbsp; s.setId(1);<br />
&nbsp; &nbsp; &nbsp; &nbsp; s.setName("bromon");<br />
&nbsp; &nbsp; &nbsp; &nbsp; s.setPassword("123");<br />
&nbsp; &nbsp; &nbsp; &nbsp; s.setGrade(1);<br />
&nbsp; &nbsp; &nbsp; &nbsp; s.setSex(0);<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; sm.add(s);<br />
}</pre>
<br />
<br />
通过以上的代码可以看出，spring可以简单的把普通的java class纳入事务管理，声明性的事务操作起来也很容易。有了spring之后，声明性事务不再是EJB独有，我们不必为了获得声明性事务的功能而去忍受EJB带来的种种不便。<br />
<br />
我所使用的mysql是不支持事务的，你可以更换使用PostgreSQL，有了spring+hibernate，更换db并不像以前那样恐怖了，步骤很简单：<br />
<br />
1、 添加PostgreSQL的jdbc驱动<br />
2、 修改dataSource配置，包括驱动名称、url、帐号、密码<br />
3、 修改sessionFactory的数据库dailet为net.sf.hibernate.dialect.PostgreSQLDialect<br />
4、 修改hbm.xml中的主键生成策略为increment<br />
<br />
所有的修改都在配置文件中完成，业务代码不需要任何修改，我很满意，How about u?<br />
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><a id="viewpost1_TitleUrl" href="http://www.blogjava.net/kaktos/archive/2006/03/08/34301.html">spring声明式事务管理的两种方式</a></h2>
<div class="postText">传统的：<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,128,128)">&nbsp;<font size="1">1</font></span><font size="1">&nbsp;<span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;class</span><span style="color: rgb(0,0,255)">="org.apache.commons.dbcp.BasicDataSource"</span><span style="color: rgb(255,0,0)">&nbsp;destroy-method</span><span style="color: rgb(0,0,255)">="close"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;2</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="driverClassName"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="oracle.jdbc.driver.OracleDriver"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;3</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="url"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="jdbc:oracle:thin:@127.0.0.1:1521:dev"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;4</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="username"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="kaktos"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;5</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="password"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="kaktos"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;6</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;7</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;8</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="txManager"</span><span style="color: rgb(255,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;9</span>&nbsp;<span style="color: rgb(255,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: rgb(0,0,255)">="org.springframework.jdbc.datasource.DataSourceTransactionManager"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">10</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;ref</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">11</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">12</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">13</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="businessBean"</span><span style="color: rgb(255,0,0)"><br />
</span><span style="color: rgb(0,128,128)">14</span>&nbsp;<span style="color: rgb(255,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: rgb(0,0,255)">="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">15</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionManager"</span><span style="color: rgb(255,0,0)">&nbsp;ref</span><span style="color: rgb(0,0,255)">="txManager"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">16</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="target"</span><span style="color: rgb(255,0,0)">&nbsp;ref</span><span style="color: rgb(0,0,255)">="businessBeanTarget"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">17</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionAttributes"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">18</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">props</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: rgb(0,128,128)">19</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">prop&nbsp;</span><span style="color: rgb(255,0,0)">key</span><span style="color: rgb(0,0,255)">="*"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">PROPAGATION_REQUIRED</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">prop</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">20</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">props</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">21</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">property</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">22</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">23</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: rgb(0,128,128)">24</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="businessBeanTarget"</span><span style="color: rgb(255,0,0)">&nbsp;class</span><span style="color: rgb(0,0,255)">="sample.spring.trans.BusinessBean"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">25</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;ref</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">26</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span></font></div>
<br />
这样做的弊端就是不得不为每个需要事务的bean做一次声明，如果所有的bean都基本上有一致的配置，这样就太繁琐啦。<br />
下面是第二种方式：<br />
<div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,128,128)">&nbsp;1</span>&nbsp;<font size="1"><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">beans</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;2</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;class</span><span style="color: rgb(0,0,255)">="org.apache.commons.dbcp.BasicDataSource"</span><span style="color: rgb(255,0,0)">&nbsp;destroy-method</span><span style="color: rgb(0,0,255)">="close"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;3</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="driverClassName"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="oracle.jdbc.driver.OracleDriver"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;4</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="url"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="</span><span style="color: rgb(0,0,255)">jdbc:oracle:thin:@127.0.0.1:1521:dev</span><span style="color: rgb(0,0,255)">"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;5</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="username"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="kaktos"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;6</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="password"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="kaktos"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;7</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;8</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">&nbsp;9</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="txManager"</span><span style="color: rgb(255,0,0)"><br />
</span><span style="color: rgb(0,128,128)">10</span>&nbsp;<span style="color: rgb(255,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: rgb(0,0,255)">="org.springframework.jdbc.datasource.DataSourceTransactionManager"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">11</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;ref</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">12</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">13</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">14</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="matchAllWithPropReq"</span><span style="color: rgb(255,0,0)"><br />
</span><span style="color: rgb(0,128,128)">15</span>&nbsp;<span style="color: rgb(255,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: rgb(0,0,255)">="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">16</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionAttribute"</span><span style="color: rgb(255,0,0)">&nbsp;value</span><span style="color: rgb(0,0,255)">="PROPAGATION_REQUIRED"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">17</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">18</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: rgb(0,128,128)">19</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="matchAllTxInterceptor"</span><span style="color: rgb(255,0,0)">&nbsp;class</span><span style="color: rgb(0,0,255)">="org.springframework.transaction.interceptor.TransactionInterceptor"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">20</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionManager"</span><span style="color: rgb(255,0,0)">&nbsp;ref</span><span style="color: rgb(0,0,255)">="txManager"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">21</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionAttributeSource"</span><span style="color: rgb(255,0,0)">&nbsp;ref</span><span style="color: rgb(0,0,255)">="matchAllWithPropReq"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">22</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">23</span>&nbsp;<span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">24</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="autoProxyCreator"</span><span style="color: rgb(255,0,0)"><br />
</span><span style="color: rgb(0,128,128)">25</span>&nbsp;<span style="color: rgb(255,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: rgb(0,0,255)">="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">26</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="interceptorNames"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">27</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">list</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">28</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">idref&nbsp;</span><span style="color: rgb(255,0,0)">local</span><span style="color: rgb(0,0,255)">="matchAllTxInterceptor"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">29</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">list</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">30</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">property</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">31</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="beanNames"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">32</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">list</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">33</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">idref&nbsp;</span><span style="color: rgb(255,0,0)">local</span><span style="color: rgb(0,0,255)">="businessBean"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">34</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">list</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">35</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">property</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">36</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">37</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: rgb(0,128,128)">38</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">&lt;!--</span><span style="color: rgb(0,128,0)">&nbsp;&nbsp;my&nbsp;beans&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">--&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">39</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">bean&nbsp;</span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="businessBean"</span><span style="color: rgb(255,0,0)">&nbsp;class</span><span style="color: rgb(0,0,255)">="sample.spring.trans.BusinessBean"</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">40</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">property&nbsp;</span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;ref</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">/&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">41</span>&nbsp;<span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
</span><span style="color: rgb(0,128,128)">42</span>&nbsp;<span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">beans</span><span style="color: rgb(0,0,255)">&gt;</span></font></div>
<br />
<span style="color: rgb(0,0,255)">BeanNameAutoProxyCreator<font color="#000000">会在applicationcontext初始化后自动为beanNames属性中的bean建立proxy。</font></span><br />
</div>
</div>
</div>
<img src ="http://www.blogjava.net/masen/aggbug/206269.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/masen/" target="_blank">Masen</a> 2008-06-06 11:12 <a href="http://www.blogjava.net/masen/articles/206269.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jamon</title><link>http://www.blogjava.net/masen/articles/172495.html</link><dc:creator>Masen</dc:creator><author>Masen</author><pubDate>Thu, 03 Jan 2008 07:35:00 GMT</pubDate><guid>http://www.blogjava.net/masen/articles/172495.html</guid><wfw:comment>http://www.blogjava.net/masen/comments/172495.html</wfw:comment><comments>http://www.blogjava.net/masen/articles/172495.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/masen/comments/commentRss/172495.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/masen/services/trackbacks/172495.html</trackback:ping><description><![CDATA[<div id="related_topics">&nbsp;</div>
/** <br />
*作者：张荣华(ahuaxuan) <br />
*2007-8-15 <br />
*转载请注明出处及作者 <br />
*/ <br />
<br />
前两天在看Spring内置的拦截器的时候，发现了一个之前没有注意的类：org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor，好奇心促使我上网查了一下这个jamon。大概看了一下之后发现这个玩意还真挺好用的而且挺重要的，而且现在国内对它的介绍也很少，所以写了一篇文章和大家分享。 <br />
<br />
一，Jamon简介： <br />
Jamon的全名是：Java Application Monitor。它是一个小巧的，免费的，高性能的，线程安全的性能监测工具。它可以用来测定系统的性能瓶颈，也可以用来监视用户和应用程序之间的交互情况。 Jamon主要是用来检测jee的应用程序。它最新的版本是2.1，可以用在1.4以上的jdk上。 <br />
<br />
二，将jamon导入到你的应用程序中去 <br />
首先下载jamon的开发包，见我的附件，同时你也可以去Sourceforge上自己下载。Sourceforge的下载地址为http://jamonapi.sourceforge.net。解压之后可以得到一个jar包和一个war包。jar包是自己会用到的，而war包是一个例子（不要小看这个例子，待会也要把它导入到项目中）。把war包之间丢到服务器上，访问：localhost:8080/jamon就可以看到这个例子了，这个例子是一个简单的性能监控系统。 <br />
<br />
接着把例子中的所有的包都导入到项目中，并把war包中的jsp和images还有css都考到项目中，比如新建一个目录叫monitor（它和WEB-INF是同级目录）。 <br />
<br />
三，正确配置自己的应用 <br />
我们在性能监测的时候最监测的就是页面的访问率和类中方法的访问率。所以在这一部分主要讲解一下如何监测自己的页面和类中方法的访问。 <br />
<br />
1， 检测自己的页面访问率 <br />
首先我们需要在web.xml中添加一个filter，这个filter就是用来判断哪些页面需要被监视的，如下所示： <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/112172#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;filter&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-name&gt;JAMonFilter&lt;/filter-name&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-</span><span class="keyword">class</span><span>&gt;com.easywebwork.filter.EasyPageMonFilter&lt;/filter-</span><span class="keyword">class</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/filter&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-mapping&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-name&gt;JAMonFilter&lt;/filter-name&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;url-pattern&gt;/*&lt;/url-pattern&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/filter-mapping&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&lt;filter&gt;
&lt;filter-name&gt;JAMonFilter&lt;/filter-name&gt;
&lt;filter-class&gt;com.easywebwork.filter.EasyPageMonFilter&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;JAMonFilter&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</pre>
接下来我们看看这个filter的写法： <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/112172#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="comment">/** </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;*&nbsp;@author&nbsp;张荣华（ahuaxuan） </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;* </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;*&nbsp;@since&nbsp;2007-8-13 </span>&nbsp;</span></li>
    <li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;PageMonFilter&nbsp;</span><span class="keyword">extends</span><span>&nbsp;JAMonFilter{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">long</span><span>&nbsp;serialVersionUID&nbsp;=&nbsp;5746197114960908454L; &nbsp;&nbsp;</span></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;doFilter(ServletRequest&nbsp;request,&nbsp;ServletResponse&nbsp;response,&nbsp;FilterChain&nbsp;filterChain)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;IOException,&nbsp;ServletException&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Monitor&nbsp;allPages&nbsp;=&nbsp;MonitorFactory.start(</span><span class="keyword">new</span><span>&nbsp;MonKeyImp(</span><span class="string">"org.easywebwork.allPages"</span><span>,getURI(request),</span><span class="string">"ms."</span><span>)); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里就是我们要监视的所有的页面的配置 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Monitor&nbsp;monitor&nbsp;=&nbsp;MonitorFactory.start(getURI(request)); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//这里就是我们要监视的某个页面的配置 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&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;filterChain.doFilter(request,&nbsp;response); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">finally</span><span>&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;monitor.stop(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allPages.stop(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;String&nbsp;getURI(ServletRequest&nbsp;request)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(request&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;HttpServletRequest)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;((HttpServletRequest)&nbsp;request).getRequestURI(); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span><span class="keyword">else</span><span>&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="string">"Not&nbsp;an&nbsp;HttpServletRequest"</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;FilterConfig&nbsp;filterConfig&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>}}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">/**
* @author 张荣华（ahuaxuan）
*
* @since 2007-8-13
*/
public class PageMonFilter extends JAMonFilter{
private static final long serialVersionUID = 5746197114960908454L;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
Monitor allPages = MonitorFactory.start(new MonKeyImp("org.easywebwork.allPages",getURI(request),"ms."));
//这里就是我们要监视的所有的页面的配置
Monitor monitor = MonitorFactory.start(getURI(request));
//这里就是我们要监视的某个页面的配置
try {
filterChain.doFilter(request, response);
} finally {
monitor.stop();
allPages.stop();
}
}
protected String getURI(ServletRequest request) {
if (request instanceof HttpServletRequest) {
return ((HttpServletRequest) request).getRequestURI();
} 	else {
return "Not an HttpServletRequest";
}
}
private FilterConfig filterConfig = null;
}}
</pre>
<br />
这个类看上去很简单，其实也挺简单的，就是得到uri，然后把它注册到MonitorFactory类中。这样只要我们去访问刚才创建的monitor目录下的jsp就可以看到性能监测页面了。 <br />
<br />
2， ，接下来我们看看在使用spring的情况下如何监测一个bean的方法调用。Spring也提供了对Jamon的支持(spring支持的东西还真多啊)，也就是文章开头提出的那个拦截器，为了给我们的bean加上拦截器，我们在spring的applicationcontext配置文件中加入如下语句： <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/112172#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;bean&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"</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">"beanNames"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;list&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;userService&lt;/value&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/list&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">"interceptorNames"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;list&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;jamonInterceptor&lt;/value&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/list&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>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;bean&nbsp;id=</span><span class="string">"jamonInterceptor"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor"</span><span>&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 class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"&gt;
&lt;property name="beanNames"&gt;
&lt;list&gt;
&lt;value&gt;userService&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;property name="interceptorNames"&gt;
&lt;list&gt;
&lt;value&gt;jamonInterceptor&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="jamonInterceptor" class="org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor"&gt;
&lt;/bean&gt;</pre>
<br />
上面这个是典型的spring的aop的配置，如果对spring的aop配置不了解的可以去看一下spring中文文档，当然如果不想了解的话即使直接把这段配置拷到自己的项目中也是可以直接使用的。 <br />
<br />
还有一个步骤就是在你的log4j.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://www.javaeye.com/topic/112172#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" _counted="undefined" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>log4j.logger.org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor&nbsp;=&nbsp;TRACE&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">log4j.logger.org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor = TRACE</pre>
<br />
如果没有这一行，那么这个拦截器是不会把方法调用的信息向MonitorFactory注册的。 <br />
<br />
只需要这些步骤，userservice中的方法在调用的时候就可以被拦截，然后将其注册到MonitorFactory中去了。 <br />
<br />
所有的配置完成之后我们来看一下效果吧: <br />
<a href="http://www.javaeye.com/topics/download/b2bac96e-6c18-4340-b7e0-f84c7bb6adca">http://www.javaeye.com/topics/download/b2bac96e-6c18-4340-b7e0-f84c7bb6adca</a>从这个图上我们可以看到，所有页面被访问的次数，UserService中的getAllUsers被调用的次数，最右边的是访问时间。这只是整个图的一部分，当然这个页面中也包括每一个页面被访问的次数和第一次访问的时间等等。下载附件运行，就可以看到所有的页面了。 <br />
<br />
三，总结 <br />
根据以上的步骤，我们就可以监测我们的程序了，应用程序中哪些页面被访问的多，哪些页面被访问的少，哪些方法被访问的多，哪些方法被访问的少，以及访问高峰期集中在什么时间等等，有了这些参数，我们更可以有针对性的对应用程序进行优化了，比如说某个页面访问比较频繁，我就可以用ehcache或oscache给这个页面做一个缓存。如果某个方法的访问比较频繁那就看看这个方法能否进一步优化，是需要异步，还是需要缓存，还是需要其他等等，总之有了jamon可以给我们带来更多的便捷，既可以让我们知道我们的客户的行为，也可以让我们知道我们开发的程序的&#8220;能力&#8221;。 <br />
<br />
其实本文提供的只是对页面和方法调用的监控，但是jamon可以提供更多功能，比如说sql语句的监控等等，这就需要我们共同去发掘了。 <br />
<br />
附件中包括了一个easywebwork的例子，我把jamon导入到这个例子工程中去，大家可以直接下载运行观看效果。Easywebwork是一个旨在减少webwork2.2.x系列的xml配置文件的项目， <br />
如果对这个主题感兴趣请到 <br />
<a href="http://www.javaeye.com/topic/91614">http://www.javaeye.com/topic/91614</a> <br />
<a href="http://www.javaeye.com/topic/93814">http://www.javaeye.com/topic/93814</a> <br />
参加讨论。 <br />
<img src ="http://www.blogjava.net/masen/aggbug/172495.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/masen/" target="_blank">Masen</a> 2008-01-03 15:35 <a href="http://www.blogjava.net/masen/articles/172495.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring 中的数据源</title><link>http://www.blogjava.net/masen/articles/118701.html</link><dc:creator>Masen</dc:creator><author>Masen</author><pubDate>Sun, 20 May 2007 08:40:00 GMT</pubDate><guid>http://www.blogjava.net/masen/articles/118701.html</guid><wfw:comment>http://www.blogjava.net/masen/comments/118701.html</wfw:comment><comments>http://www.blogjava.net/masen/articles/118701.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/masen/comments/commentRss/118701.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/masen/services/trackbacks/118701.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1、使用Spring自带的DriverManagerDataSource&nbsp;&nbsp; 配置文件&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"&nbsp;"http://www.springframework.org/dtd/...&nbsp;&nbsp;<a href='http://www.blogjava.net/masen/articles/118701.html'>阅读全文</a><img src ="http://www.blogjava.net/masen/aggbug/118701.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/masen/" target="_blank">Masen</a> 2007-05-20 16:40 <a href="http://www.blogjava.net/masen/articles/118701.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>