1 准备知识
1.1 JDBC处理事务
事务的处理,就是先关闭Connection的AutoCommit,执行完业务操作后,再手动commit或rollback。
Connection con = ...
// 关闭自动提交
con.setAutoCommit(false);
// 业务处理
aDao.insert(...);
bDao.insert(...);
try{
// 提交
con.commit();
}catch (Exception e){
// 回滚
con.rollback();
}
// 恢复自动提交
con.setAutoCommit(true);
1.2 Spring的AOP
在Spring的AOP代理类JdkDynamicAopProxy和ObjenesisCglibAopProxy中增加方法的时候,有下面几个步骤:
- 1 调用
DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice获取一个org.aopalliance.intercept.MethodInterceptor的list; - 2 用这个MethodInterceptor的list创建
ReflectiveMethodInvocation对象,并调用proceed()方法; - 3 TransactionInterceptor是list其中的一个MethodInterceptor,用来执行事务。
有关Spring AOP具体实现可以查看 Spring AOP源码实现分步解析 。
2 Spring事务控制
- Spring的事务控制,就是利用AOP,在业务方法执行前通过DataSource拿到Connection,然后setAutoCommit(false);业务方法执行完后再commit或rollback。
- 事务处理在TransactionInterceptor.invoke中进行;
- TransactionInterceptor调用里父类
TransactionAspectSupport的invokeWithinTransaction方法进行具体的事务控制。
2.1 几个重要的类
2.1.1 TransactionAttribute
事务属性,TransactionDefinition的子类
- TransactionDefinition默认实现类
DefaultTransactionDefinition; - TransactionAttribute的实现类都继承了DefaultTransactionDefinition;
- TransactionDefinition定义事务相关属性:
// 事务传播模式
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;
// 事务隔离级别,使用java.sql.Connection.TRANSACTION*定义
int ISOLATION_DEFAULT = -1; // 默认,使用数据库的隔离级别
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED; //读未提交
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED; // 读已提交
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ; // 可重复读
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE; // 序列化
- DefaultTransactionDefinition的主要属性:
private int propagationBehavior = PROPAGATION_REQUIRED; // 事务传播方式
private int isolationLevel = ISOLATION_DEFAULT; // 事务隔离级别
private int timeout = TIMEOUT_DEFAULT; // 超时时间
- 实现类:
- RuleBasedTransactionAttribute
- DefaultTransactionAttribute
2.1.2 PlatformTransactionManager
事务管理器
- 方法:
- TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; // 根据TransactionDefinition创建TransactionStatus
- void commit(TransactionStatus status) throws TransactionException; // 提交
- void rollback(TransactionStatus status) throws TransactionException; // 回滚
- 实现类:
- DataSourceTransactionManager
- AbstractPlatformTransactionManager
2.1.3 TransactionStatus
事务状态的操作类
SavepointManager的子类- 各种状态及Savepoint的创建/回滚/释放等
- 实现类:
- AbstractTransactionStatus
- DefaultTransactionStatus
2.1.4 TransactionInfo
- 事务信息的类,包括事务管理器,事务属性等;
- 通过createTransactionIfNecessary创建;
- 重要属性:
- PlatformTransactionManager
- TransactionAttribute
- joinpointIdentification : 切入方法,如com.xx.yy.MockService.mockInsert
- TransactionStatus
2.2 事务执行过程
2.2.1 invokeWithinTransaction
invokeWithinTransaction是执行事务的主流程
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 1. 获取事务属性,没有则表示当前不在事务中
/*
TransactionAttributeSource: 事务属性源,用来获取事务属性,如 org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
TransactionAttribute:事务属性,如 org.springframework.transaction.interceptor.RuleBasedTransactionAttribute
*/
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 2. 获取PlatformTransactionManager,如DataSourceTransactionManager。
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 3. 待执行的切入方法,如 com.xx.yy.MockService.mockInsert
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 4.事务不存在或不是编程式事务,则尝试创建或获取事务,并执行commit/rollback等。
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
// 5 执行业务代码 即service中的方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 回滚,如果有SavePoint,则回滚到SavePoint。
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
// 6 执行Connection.commit()
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
// TransactionTemplate.execute中使用TransactionCallback进行的回调式的事务处理
// 省略代码
}
}
2.2.2 创建TransactionAttribute
ProxyTransactionManagementConfiguration在创建TransactionInterceptor的Bean时,通过new AnnotationTransactionAttributeSource()创建了TransactionAttributeSource,并设置到interceptor中。
AnnotationTransactionAttributeSource.getTransactionAttribute经多层调用,最终调用到determineTransactionAttribute方法,使用SpringTransactionAnnotationParser解析AnnotatedElement;
SpringTransactionAnnotationParser.parseTransactionAnnotation:
- AnnotatedElementUtils.findMergedAnnotationAttributes将AnnotabledElement及Transactional解析为AnnotationAttributes;
- 解析AnnotationAttributes,设置传播类型,隔离级别等。返回RuleBasedTransactionAttribute。
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<>();
Class<?>[] rbf = attributes.getClassArray("rollbackFor");
for (Class<?> rbRule : rbf) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
String[] rbfc = attributes.getStringArray("rollbackForClassName");
for (String rbRule : rbfc) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
for (Class<?> rbRule : nrbf) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
for (String rbRule : nrbfc) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
rbta.getRollbackRules().addAll(rollBackRules);
return rbta;
}
2.2.3 获取PlatformTransactionManager
- PlatformTransactionManager已经在系统启动时声明为Bean;
- determineTransactionManager方法中,通过
defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);获取。
2.2.4 创建TransactionInfo
TransactionInfo对象在TransactionAspectSupport.createTransactionIfNecessary中创建:
- 通过
PlatformTransactionManager.getTransaction创建TransactionStatus; - 用创建的TransactionStatus和其他属性,通过
prepareTransactionInfo方法创建TransactionInfo对象。
// 创建TransactionInfo
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, String joinpointIdentification,
@Nullable TransactionStatus status) {
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
// We need a transaction for this method...
if (logger.isTraceEnabled()) {
logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
// The transaction manager will flag an error if an incompatible tx already exists.
txInfo.newTransactionStatus(status);
}
else {
// The TransactionInfo.hasTransaction() method will return false. We created it only
// to preserve the integrity of the ThreadLocal stack maintained in this class.
if (logger.isTraceEnabled())
logger.trace("Don't need to create transaction for [" + joinpointIdentification +
"]: This method isn't transactional.");
}
// We always bind the TransactionInfo to the thread, even if we didn't create
// a new transaction here. This guarantees that the TransactionInfo stack
// will be managed correctly even if no transaction was created by this aspect.
/*
将TransactionStatus绑定到当前ThreadLocal中,并备份旧的TransactionStatus。
*/
txInfo.bindToThread();
return txInfo;
}
2.2.5 创建TransactionStatus
由AbstractPlatformTransactionManager.getTransaction创建
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
/*
1. 获取 DataSourceTransactionObject;
DataSourceTransactionManager.doGetTransaction方法中如果允许嵌套事务,则允许设置Savepoint,以支持嵌套事务.
*/
Object transaction = doGetTransaction();
// Cache debug flag to avoid repeated checks.
boolean debugEnabled = logger.isDebugEnabled();
if (definition == null) {
// 2. 如果前面没有创建TransactionAttribute(TransactionDefinition的子类),则这里创建一个默认值的DefaultTransactionDefinition。
definition = new DefaultTransactionDefinition();
}
// 事务是否存在,通过DataSourceTransactionObject.txObject.getConnectionHolder().isTransactionActive()判断
if (isExistingTransaction(transaction)) {
/*
3. 如果存在,则根据definition.getPropagationBehavior()进行不同处理:
(1) PROPAGATION_NEVER : throw new IllegalTransactionStateException
(2) PROPAGATION_NOT_SUPPORTED : 挂起当前事务,最终是执行了doSuspend方法,对DataSourceTransactionObject执行setConnectionHolder(null),并解绑DataSource。
(3) PROPAGATION_REQUIRES_NEW : 挂起当前事务,创建新的DefaultTransactionStatus,并指定doBegin方法。即创建新的事务。
(4) PROPAGATION_NESTED: 如果nestedTransactionAllowed==false(默认是false,开启需要手动指定),则throw new NestedTransactionNotSupportedException。
创建新的DefaultTransactionStatus,并执行createAndHoldSavepoint()创建SavePoint。
*/
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// 以下是事务不存在的处理
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
// 传播行为是PROPAGATION_MANDATORY,根据行为定义,则需要抛出异常。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 执行 setAutoCommit等
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
2.2.6 doBegin
DataSourceTransactionManager.doBegin
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
// 1. 从DataSource中获取Connection
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
// 2. 设置ConnectionHolder 以备后面使用
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
// 3. 获取Connection
con = txObject.getConnectionHolder().getConnection();
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
// 4. 设置Connection的readOnly和transactionIsolation(事务隔离级别)。
txObject.setPreviousIsolationLevel(previousIsolationLevel);
if (con.getAutoCommit()) {
// 执行完后必须恢复AutoCommit
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
// 4. 禁止AutoCommit
con.setAutoCommit(false);
}
// prepareTransactionalConnection方法中,如果是(isEnforceReadOnly() && definition.isReadOnly()),会执行`stmt.executeUpdate("SET TRANSACTION READ ONLY");`
prepareTransactionalConnection(con, definition);
txObject.getConnectionHolder().setTransactionActive(true);
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// Bind the connection holder to the thread.
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
}
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}