Spring 事务模板方法设计模式

Posted linlf03

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 事务模板方法设计模式相关的知识,希望对你有一定的参考价值。

接上一篇文章

上一篇讲到了doGetTransaction方法

技术图片

 

一、模板方法设计模式

这里涉及到了一个经典的设计模式:模板方法

如下图:

技术图片

AbstractPlatformTransactionManager实现了PlatformTranscationManager接口

DatasourceTransactionManager,HibernateTransactionManager等继承了AbstractPlatformTransactionManager类

AbstractPlatformTransactionManager类中定义了事务处理的若干方法。 其中获得事务,提交事务,回滚事务由具体的子类实现。

 

二、进入doGetTransaction的其中一个实现类Hibernate3中的HibernateTransactionManager 类

进入doGetTransaction方法

	@Override
	protected Object doGetTransaction() 
		HibernateTransactionObject txObject = new HibernateTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());

		SessionHolder sessionHolder =
				(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
		if (sessionHolder != null) 
			if (logger.isDebugEnabled()) 
				logger.debug("Found thread-bound Session [" +
						SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction");
			
			txObject.setSessionHolder(sessionHolder);
		
		else if (this.hibernateManagedSession) 
			try 
				Session session = getSessionFactory().getCurrentSession();
				if (logger.isDebugEnabled()) 
					logger.debug("Found Hibernate-managed Session [" +
							SessionFactoryUtils.toString(session) + "] for Spring-managed transaction");
				
				txObject.setExistingSession(session);
			
			catch (HibernateException ex) 
				throw new DataAccessResourceFailureException(
						"Could not obtain Hibernate-managed Session for Spring-managed transaction", ex);
			
		

		if (getDataSource() != null) 
			ConnectionHolder conHolder = (ConnectionHolder)
					TransactionSynchronizationManager.getResource(getDataSource());
			txObject.setConnectionHolder(conHolder);
		

		return txObject;
	

  

1、创建HibernateTransactionObject对象

HibernateTransactionObject txObject = new HibernateTransactionObject();

HibernateTransactionObject 是一个Hibernate事务对象,代表一个SessionHolder。被HibernateTransactionManger用作事务对象。

技术图片

 

2、进入SessionHolder

SessionHolder: session持有者,包装了一个Hibernate Session和一个Hibernate事务

技术图片

 

三 、进入doGetTransaction的其中一个实现类JDBC中的DataSourceTransactionManager 类

进入doGetTransaction方法

	@Override
	protected Object doGetTransaction() 
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		ConnectionHolder conHolder =
		    (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	

  

1、创建DataSourceTransactionObject实例
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
进入DataSourceTransactionObject

技术图片

DataSourceTransactionObject也是继承自JdbcTransactionObjectSupport

三、回到AbstractPlatformTransactionManager类的getTransaction方法
进入如下代码

技术图片

如果已经存在事务,则检查事务的传播行为

 

2、进入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);
				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.
		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 事务模板方法设计模式的主要内容,如果未能解决你的问题,请参考以下文章

Spring中的设计模式:模板模式

spring事务详解实例

spring4.0事务超详细源码解析

spring4.0事务超详细源码解析

spring4.0事务超详细源码解析

原来Spring源码中的模板方法设计模式可以这么简单!GET到了!