周末无事,复习了下spring声明式事务管理,写出以下总结,算是做一个小小的笔记。
大多数Spring用户选择声明式事务管理。这是对应用代码影响最小的选择,因此也最符合 非侵入式轻量级容器的理念。
在理解Spring的声明式事务管理方面最重要的概念是:
Spring的事务管理是通过AOP代理实现的。 其中的事务通知由元数据(目前基于XML或注解)驱动。 代理对象与事务元数据结合产生了一个AOP代理,它使用一个PlatformTransactionManager 实现品配合TransactionInterceptor,在方法调用前后实施事务。
废话不多说,先写配置,再做解释。
Spring的声明式事务管理是通过Spring AOP实现的,因为事务方面的代码与Spring绑定并以一种样板式风格使用, 不过尽管如此,你一般并不需要理解AOP概念就可以有效地使用Spirng的声明式事务管理。
这里我说的spring事务管理有两种方式:1.annotation(注解形式);2.xml形式
一:先说annotation(注解)形式的使用方法:
1.java代码:
@Transactional()
public void add(User user) {
userDAO.save(user);
Log log = new Log();
log.setMsg("a user saved!");
logDAO.save(log);
}
2.bean.xml代码
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
<span style="color:#ff0000;">xmlns:tx="http://www.springframework.org/schema/tx"</span>
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
<span style="color:#ff0000;"> http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd</span>">
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
接下来分析一下上面的代码:
java代码就不用说了,在方法上加入@Transactional 注解即可,重点说一下bean.xml的配置;
首先在bena.xml加入tx的引用,和相应的 schema。如上面红色的代码。
先看<tx:annotation-driven> annotation驱动,这里是需要配置一个annotation驱动,其属性transaction-manager,字面理解:事务管理者。这句话我的理解是,在给annotation驱动时候需要一个事务管理者。而这个事务管理者,我们在看配置<bean id="txManager"> 我这里做测试用的是hibernate。所以这里就用HibernateTransactionManager。当然也可以用jdbc的transaction(org.springframework.jdbc.datasource.DataSourceTransactionManager)也可以。而事务管理呢其实就是给需要管理的方法前后加一个try catch,当捕获到异常的时候,就rollback。所以这里就用到了aop-切面编程。事务管理又是针对数据库来说的,所以我们这里需要给他一个指定数据库,所以我们在这个bean里面还有一句话<property name="sessionFactory" ref="sessionFactory" /> 把sessionfactory注入进去。当然sessionFaction里面注入的也有datasources,这里不多做解释。
annotation式的事务配置就算结束了,是不是感觉很简单呀。但是问题来了。如果我有很多方法,需要加事务,是不是我要在每个需要事务管理的方法上面都要加一个@transaction的注解呢。回答是肯定的。可是这样一来好像也不怎么简单了,每个都加注解,多麻烦呀。所以接下来介绍两外一种方式--XML形式的事务管理配置。
二:XML形式
java代码的配置就不说了,因为在xml形式的事务配置里面是不要在java代码里面做任何动作的。
直接看xml的配置
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="add*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="bussinessService"
expression="execution(public * com.rango.service..*.*(..))" />
<aop:advisor pointcut-ref="bussinessService"
advice-ref="txAdvice" />
</aop:config>
因为这里不需要注解,所以<tx:annotation-driven> 这个配置就不需要了。
<tx:advice/> 把所有get开头的方法都执行只读事务。add方法执行REQUIRED(当其他方法调用此方法时候,如果有事务则用原来的,如果么有则新建一个事务)这也是propagation的默认值。propagation和read-only等这些是transaction的一些属性,回头写一篇关于属性设置的文章详细介绍一下。这里同样有一个transaction-manager="txManager"事务管理者。
在最后 一个配置<aop:config> 中 <aop:pointcut/> 元素定义是AspectJ的切面表示法.在这里我们看到了这样一个配置:expression="execution(public * com.rango.service..*.*(..))"这样写等于spring会扫描com.rango.service.下所有文件夹中所有的文件的方法都加入事务。这样一来就不需要我们像annotation那样,每个方法都加入一个注解。相比之下省事了不少吧。
接下来给它一个建议:<aop:advisor> 首先需要一个pointcut的引用,和advice的引用。至此xml形式的事务管理也配置完了。相比之下xml形式更常用一点。当然里面还有很多细节比如上面提到的transaction的一些属性的理解啥的,这后面再单独介绍吧。
在spring3.+以后都有自己的一些新特性,比如对rest的支持等。但是在事务管理者方面其实都还差不多的.