Spring源码分析(五)

本文介绍了Spring框架中声明式事务管理的配置方法及原理。包括XML配置方式与注解配置方式,并深入分析了TransactionInterceptor的工作机制,事务传播行为以及如何通过配置实现不同类型的事务需求。

spring事务分为编程式事务管理和声明式事务管理,重点说明下声明式事务管理。

配置方式有两种:

1、xml配置advice

2、注解配置@Transactional

xml配置样例如下:

	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException"/>
			<tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException"/>
			<tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException"/>
		</tx:attributes>
	</tx:advice>
	
	<aop:config>
		<aop:pointcut id="transactionPointcut" expression="execution(* com.xxx.service.impl.*.*(..))" />
		<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
	</aop:config>

tx命名空间扩展配置

http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler

public void init() {
	// advice节点解析
	registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
	// 开启注解事务的解析
	registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
	registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}

advice解析类TxAdviceBeanDefinitionParser,对应连接器为TransactionInterceptor

	@Override
	protected Class<?> getBeanClass(Element element) {
		return TransactionInterceptor.class;
	}

设置类TransactionInterceptor的transactionManager和transactionAttributeSource

protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {

	// 设置TransactionInterceptor的transactionManager属性
	builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));

	List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
	if (txAttributes.size() > 1) {
		parserContext.getReaderContext().error(
				"Element <attributes> is allowed at most once inside element <advice>", element);
	}
	else if (txAttributes.size() == 1) {
		// Using attributes source.
		Element attributeSourceElement = txAttributes.get(0);
		// 解析attributes节点<tx:attributes>
		RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
		// 设置TransactionInterceptor的transactionAttributeSource属性
		builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
	}
	else {
		// Assume annotations source.
		builder.addPropertyValue("transactionAttributeSource",
				new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
	}
}

TransactionInterceptor的transactionAttributeSource属性类型:NameMatchTransactionAttributeSource

NameMatchTransactionAttributeSource的nameMap属性保存事务方法

nameMap的结构是map,其中key:method节点的name,value:RuleBasedTransactionAttribute类型(封装propagation、isolation、timeout、read-only等属性)

private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) {
	List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT);
	ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap =
		new ManagedMap<TypedStringValue, RuleBasedTransactionAttribute>(methods.size());
	transactionAttributeMap.setSource(parserContext.extractSource(attrEle));

	for (Element methodEle : methods) {
		String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE);
		TypedStringValue nameHolder = new TypedStringValue(name);
		nameHolder.setSource(parserContext.extractSource(methodEle));

		RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute();
		// 事务传播行为
		String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE);
		// 事务隔离级别
		String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE);
		// 超时时间
		String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE);
		// 只读属性
		String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE);
		if (StringUtils.hasText(propagation)) {
			attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation);
		}
		if (StringUtils.hasText(isolation)) {
			attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation);
		}
		if (StringUtils.hasText(timeout)) {
			try {
				attribute.setTimeout(Integer.parseInt(timeout));
			}
			catch (NumberFormatException ex) {
				parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle);
			}
		}
		if (StringUtils.hasText(readOnly)) {
			attribute.setReadOnly(Boolean.valueOf(methodEle.getAttribute(READ_ONLY_ATTRIBUTE)));
		}

		List<RollbackRuleAttribute> rollbackRules = new LinkedList<RollbackRuleAttribute>();
		// 事务回滚异常
		if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) {
			String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE);
			addRollbackRuleAttributesTo(rollbackRules,rollbackForValue);
		}
		// 事务不回滚异常
		if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) {
			String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE);
			addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue);
		}
		attribute.setRollbackRules(rollbackRules);
		// NameMatchTransactionAttributeSourcede的nameMap属性
		transactionAttributeMap.put(nameHolder, attribute);
	}

	RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class);
	attributeSourceDefinition.setSource(parserContext.extractSource(attrEle));
	// NameMatchTransactionAttributeSourcede的nameMap属性
	attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap);
	return attributeSourceDefinition;
}

具体的事务处理由TransactionInterceptor负责,分析下invoke方法

public Object invoke(final MethodInvocation invocation) throws Throwable {
	// Work out the target class: may be {@code null}.
	// The TransactionAttributeSource should be passed the target class
	// as well as the method, which may be from an interface.
	Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

	// Adapt to TransactionAspectSupport's invokeWithinTransaction...
	return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
		public Object proceedWithInvocation() throws Throwable {
			return invocation.proceed();
		}
	});
}

以下是事务方法的执行过程,重点是TransactionInfo对象的创建,事务的回滚和提交都围绕它进行。

// If the transaction attribute is null, the method is non-transactional.
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass);

if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
	// Standard transaction demarcation with getTransaction and commit/rollback calls.
	// 事务相关信息,由PlatformTransactionManager#getTransaction创建
	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.
		retVal = invocation.proceedWithInvocation();
	}
	catch (Throwable ex) {
		// target invocation exception
		// 事务回滚
		completeTransactionAfterThrowing(txInfo, ex);
		throw ex;
	}
	finally {
		cleanupTransactionInfo(txInfo);
	}
	// 事务提交
	commitTransactionAfterReturning(txInfo);
	return retVal;
}

getTransaction方法主要处理事务的传播行为,重点isExistingTransaction

/**
 * This implementation handles propagation behavior. Delegates to
 * {@code doGetTransaction}, {@code isExistingTransaction}
 * and {@code doBegin}.
 * @see #doGetTransaction
 * @see #isExistingTransaction
 * @see #doBegin
 */
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
	Object transaction = doGetTransaction();

	// Cache debug flag to avoid repeated checks.
	boolean debugEnabled = logger.isDebugEnabled();

	if (definition == null) {
		// Use defaults if no transaction definition given.
		definition = new DefaultTransactionDefinition();
	}

	
	if (isExistingTransaction(transaction)) {
		// Existing transaction found -> check propagation behavior to find out how to behave.
		// 当前存在事务,根据传播行为做挂起等操作
		return handleExistingTransaction(definition, transaction, debugEnabled);
	}

	// Check definition settings for new transaction.
	if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
		throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
	}

	// No existing transaction found -> check propagation behavior to find out how to proceed.
	// 支持当前事务,如果当前没有事务,就抛出异常
	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);
			// 创建新事务
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
		catch (RuntimeException ex) {
			resume(null, suspendedResources);
			throw ex;
		}
		catch (Error err) {
			resume(null, suspendedResources);
			throw err;
		}
	}
	else {
		// Create "empty" transaction: no actual transaction, but potentially synchronization.
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
	}
}

handleExistingTransaction方法

/**
 * Create a TransactionStatus for an existing transaction.
 */
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 {
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
			// 创建新的事务
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
		catch (RuntimeException beginEx) {
			resumeAfterBeginException(transaction, suspendedResources, beginEx);
			throw beginEx;
		}
		catch (Error beginErr) {
			resumeAfterBeginException(transaction, suspendedResources, beginErr);
			throw beginErr;
		}
	}

	// 如果当前存在事务,则在嵌套事务内执行
	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);
			// 创建savepoint
			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.
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, null);
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
	}

	// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
	// PROPAGATION_SUPPORTS、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);
}

spring事务传播行为如下:

PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是 最常见的选择。
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED   以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作

创建新事务

protected void doBegin(Object transaction, TransactionDefinition definition) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	Connection con = null;

	try {
		if (txObject.getConnectionHolder() == null ||
				txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
			Connection newCon = this.dataSource.getConnection();
			if (logger.isDebugEnabled()) {
				logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
			}
			txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
		}

		txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
		con = txObject.getConnectionHolder().getConnection();

		// prepareConnectionForTransaction方法内设置事务隔离级别
		Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
		txObject.setPreviousIsolationLevel(previousIsolationLevel);

		// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
		// so we don't want to do it unnecessarily (for example if we've explicitly
		// configured the connection pool to set it already).
		if (con.getAutoCommit()) {
			txObject.setMustRestoreAutoCommit(true);
			if (logger.isDebugEnabled()) {
				logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
			}
			// 关闭自动提交事务
			con.setAutoCommit(false);
		}
		txObject.getConnectionHolder().setTransactionActive(true);

		int timeout = determineTimeout(definition);
		if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
			// 设置超时时间
			txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
		}

		// Bind the session holder to the thread.
		if (txObject.isNewConnectionHolder()) {
			TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
		}
	}

	catch (Throwable ex) {
		DataSourceUtils.releaseConnection(con, this.dataSource);
		throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值