一、要弄清spring是如何进行事务管理的,首先来看两个接口:
1. TransactionDefinition 它包含了一些事务属性的定义(传播类型等)
public interface TransactionDefinition {
//....省略部分代码
//定义了7种事务的传播类型
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
//获取事务的传播类型
int getPropagationBehavior();
}
2. PlatformTransactionManager 事务管理器接口;真正的事务管理就是由这个接口的实现类来完成的。
public interface PlatformTransactionManager {
//通过事务的定义,来获取一个事务的当前状态
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
// 依照事务的状态来完成提交
void commit(TransactionStatus status) throws TransactionException;
// 回滚
void rollback(TransactionStatus status) throws TransactionException;
}
二、事务管理的实现
- spring 的事务管理分为两种方式:编程式和声明式;
<1> 编程式:使用硬编码的方式来完成事务操作。在sping里面,又有两种方式来完成编程式事务:
a.使用 PlatformTransactionManager 接口
DefaultTransactionDefinition dtd = new DefaultTransactionDefinition();//创建事务
dtd.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);//设置事务传播类别
TransactionStatus ts = transactionManager.getTransaction(dtd);//获取事务状态
try{
userStepMappingDao.add(us);//保存对象US
stepCategoryDao.add(usd);//保存对象USD
transactionManager.commit(ts);//提交
}catch(Exception e){
transactionManager.rollback(ts);//回滚
}
b.使用TransactionTemplate;看一下源码
public class TransactionTemplate extends DefaultTransactionDefinition
implements TransactionOperations, InitializingBean {
//可以看到, TransactionTemplate继承自DefaultTransactionDefinition
//内部还是使用了PlatformTransactionManager接口
private PlatformTransactionManager transactionManager;
//看一下主要的方法:
public <T> T execute(TransactionCallback<T> action)
throws TransactionException {
// 如果当前的事务管理器实现了CallbackPreferringPlatformTransactionManager接口
// ,则直接调查用接口的execute方法,这部分我们以后再看
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager)
.execute(this, action);
} else {
// 由于继承自 DefaultTransactionDefinition,直接获取事务状态
TransactionStatus status = this.transactionManager
.getTransaction(this);
T result;
try {
// 这里action.doInTransaction(status);是我们自己的应用代码
// (这里考虑是否通过反射来调用DAO里面的方法)
result = action.doInTransaction(status);
} catch (RuntimeException ex) {
// Transactional code threw application exception -> rollback
// point A:
rollbackOnException(status, ex);
throw ex;
} catch (Error err) {
// Transactional code threw error -> rollback
// point B:
rollbackOnException(status, err);
throw err;
} catch (Exception ex) {
// Transactional code threw unexpected exception -> rollback
// point C:
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex,
"TransactionCallback threw undeclared checked exception");
}
// 提交
this.transactionManager.commit(status);
return result;
}
}
可以看到,最终还是调用ransactionManager的rollback()方法。所以TransactionTemplate只是对PlatformTransactionManager作了一个内部调用而已。
<2>声明式:这也是最常用的方法,因这这种方法不会发生任何的代码侵入;
a. 使用org.springframework.transaction.interceptor.TransactionProxyFactoryBean进行手动代理
<bean id="baseTxProxy" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" /> //注入事务管理器
</property>
<!-- 这里通过target属性为某个接口加上事务,通过方法名来匹配 -->
<property name="target">
<ref bean="testTran" />//需要加事务的service
</property>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
b.使用sping AOP
<tx:annotation-driven transaction-manager="transactionManager" /> //配置事务管理器
<tx:advice id="defaultTxAdvice" transaction-manager="transactionManager"> //事务属性
<tx:attributes>
<tx:method name="*Transaction" propagation="REQUIRED" //propagation 事务传播类型
rollback-for="Exception" />//所有exception回滚,相对的还有no-rollback-for属性
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />//read-only="true"事务只读
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
<tx:method name="fetch*" propagation="SUPPORTS" read-only="true" />
<tx:method name="is*" propagation="SUPPORTS" read-only="true" />
<tx:method name="*_noTrans" propagation="NOT_SUPPORTED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="allManagerMethod" //切点
expression=" (
execution(* com.managerment.service.impl..*.*(..)) //第一个*与包路径之间有空格
//第一个* :任何返回类型 第二个* :impl下所有的类 第三个*: 所有的方法 第一个.. (即impl..) :impl下的所有子包 第二个.. (即(..)):所有参数
) " />
<aop:advisor advice-ref="defaultTxAdvice" pointcut-ref="allManagerMethod" />//通知
</aop:config>