1、Spirng事务配置文件解析入口:
AbstractBeanDefinitionParser入口方法是parse 方法
2、Spring事务调用入口:
TransactionInterceptor类实现了MethodInterceptor接口,入口方法是 invoke 方法
事务传播性
@Transaction中的propagation的可以配置事务的传播性,网上介绍的很多,就直接复制一段
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 (也是默认策略)
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常
Spring事务的传播特性是为了解决服务之间相互调用产生的一套规则,如Aservice和Bservice A为外层service B为内层service
A中调用B ,传播特性主要是针对内层事务的修饰限定词,以下为实验结论及原因
support
1、结论:A有事务,事务传播属性为support,B无事务 A无异常 B有异常 则 AB 不回滚
原因:spring在当前A的外层无事务的情况下,spring会创建一个空的transcation对象,当发生异常时,需要回滚,但transcation是空对象,所以无法回滚
源码片段:AbstractPlatformTransactionManager类的getTransaction方法;
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// Use defaults if no transaction definition given.
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(def, transaction, debugEnabled);
}
// Check definition settings for new transaction.
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
}
此片段会生产一个空对象
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
//返回一个status中transaction为null的对象
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
源码片段:AbstractPlatformTransactionManager类的processRollback方法
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean unexpectedRollback = unexpected;
try {
triggerBeforeCompletion(status);
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
}
status.rollbackToHeldSavepoint();
}
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
}
doRollback(status);
}
else {
// Participating in larger transaction
if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
}
doSetRollbackOnly(status);
}
else {
if (status.isDebug()) {
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
}
}
}
else {
logger.debug("Should roll back transaction but cannot - no transaction available");
}
// Unexpected rollback only matters here if we're asked to fail early
if (!isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = false;
}
}
}
catch (RuntimeException | Error ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
}
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
// Raise UnexpectedRollbackException if we had a global rollback-only marker
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
}
finally {
cleanupAfterCompletion(status);
}
}
此处判断没有transaction
if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
}
doSetRollbackOnly(status);
}
else {
if (status.isDebug()) {
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
}
}
}
else {
logger.debug("Should roll back transaction but cannot - no transaction available");
}
2、结论:A无事务,B有事务传播属性为support, A无异常 B有异常 则 AB 不回滚 (同第一种情况)
3、结论:A有事务,B有事务传播属性为support, A无异常 B有异常 则 AB 回滚 (AB在同一个事务中,使用A的事务)
Not support
1、A中有事务,B有事务传播属性为not support, A无异常 B有异常 则 A回滚 B 不回滚 (AB不在同一事务中)
原因:A中的事务按照原样执行,B中的事务则是挂起当前事务
源码片段:
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
required
1、结论:A有事务B有事务 A无异常 B有异常 则 AB 同时回滚 (AB使用同一个事务)
原因:spring会产生一个transaction对象,当发生异常时,可以调用rollback方法
1)源码片段:AbstractPlatformTransactionManager类的getTransaction方法;
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
2)源码片段:AbstractPlatformTransactionManager类的processRollback方法
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
}
doRollback(status);
}
2、 A有事务B无事务 A无异常 B有异常 则 AB 同时回滚 (AB处于同一个事务当中)
3、 A无事务B有事务 A无异常 B有异常 则 A不回滚 (A与B不处于同一个事务中,A无事务处理)
required new
1、 A有事务B无事务 A无异常 B有异常 则 AB 同时回滚(AB处于同一个事务当中,B包裹在A事务当中)
2、A无事务B有事务 A无异常 B有异常 则 A不回滚B回滚(A无事务B有事务)
3、A有事务B有事务,事务传播属性为required new, A无异常 B有异常 则 AB 同时回滚(AB处于不同的事务当中)
原因:A有事务,B会开一个新的事务,B出错,B会回滚,A也回回滚,因为开启的事务当中B服务抛出异常,导致A事务回滚
源码片段:
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
nerver
1、A有事务,事务属性为nerver ,B无事务 A无异常 B有异常 则 AB 不回滚(会创建空事务对象,无法回滚)
2、A有事务,B有事务传播属性为nerver, A无异常 B有异常 则 抛出异常 AB回滚
原因:外层有事务,内层事务传播属性为never 则表示外层不能有事务,抛出异常,回滚数据
AbstractPlatformTransactionManager类handleExistingTransaction方法
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
}
if (useSavepointForNestedTransaction()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
return startTransaction(definition, transaction, debugEnabled, null);
}
}
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}
if (isValidateExistingTransaction()) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
"(unknown)"));
}
}
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
}
}
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
源码片段:此处会直接抛出异常,然后回滚
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
3、A无事务B有事务 ,传播属性为nerver、A无异常 B有异常 则 A 不回滚(无事务对象)B不回滚(事务空对象
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
mandatory
1、A无事务B有事务,传播熟悉为mandatory, A无异常 B有异常 则 抛出异常No existing transaction found for transaction marked with propagation 'mandatory
原因:mandatory表示外层事务必须存在
源码片段
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(def, transaction, debugEnabled);
}
// Check definition settings for new transaction.
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
先判断是否存在外层事务,如果存在则使用外层事务,如果不存在则报错
2、A有事务B有事务 A无异常 B有异常 则 AB回滚(AB使用同一个事务)
原因:如果A有事务,B有事务,且B使用mandatory,则AB回滚(AB使用同一个事务)
源码片段:
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(def, transaction, debugEnabled);
}
nested
1、A有事务B有事务 A无异常 B有异常 则 AB回滚(AB在同一个事务中)
原因:A使用事务,B使用nested,AB存在同一个事务中
源码片段
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(def, transaction, debugEnabled);
}
2、A有事务B无事务 A无异常 B有异常 则 AB回滚
原因:A使用事务,B使用nested,AB存在同一个事务中
3、A无事务B有事务 A无异常 B有异常 则 A不回滚 B回滚
原因:A无事务,B有事务,A为外层事务,B为内层事务,A无异常,直接提交数据,B有异常,回滚
彩蛋
package cn.com.demo.service.impl;
import cn.com.demo.entity.Student;
import cn.com.demo.entity.Teacher;
import cn.com.demo.mapper.StuMapper;
import cn.com.demo.service.StuService;
import cn.com.demo.service.TeaService;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class StuServiceImpl implements StuService {
@Autowired
private StuMapper stuMapper;
@Autowired
private TeaService teaService;
/**
* 期望:在addStu2发生异常的情况下,addStu2回滚 原因:addStu2新建一个事务,在事务周期内发生回滚操作
* 结果:addStu2不发生回滚 原因:因为spring事务采用的是代理模式,在将事务组织到调用addStu这个切入点时
* 调用addStu是代理对象,但是调用addStu2却不是代理对象,是真实对象,所以事务失效,导致addStu2无法回滚
* 解决此问题,需要获取代理对象,使用代理对象来执行addStu2方法在配置文件中开启获取代理对象的配置<aop:aspectj-autoproxy expose-proxy="true"></aop:aspectj-autoproxy>
* StuService o = (StuService)AopContext.currentProxy();
* o.addStu2(student);
* @param student
* @return
*/
@Override
@Transactional
public boolean addStu(Student student) {
try{
addStu2(student);
}catch (Exception e){
e.printStackTrace();
}
stuMapper.addStu(student);
return false;
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean addStu2(Student student){
stuMapper.addStu(student);
int i = 1/0;
return false;
}
}