Spring实现事务源码分析

Spring实现事务的方式是通过代理+Aop来完成的,关于代理的相关内容,可参考以前的文章:spring Aop 实现原理

下面就以Spring实现事务的一种方式来分析这个过程。

<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
     abstract="true">
   <property name="transactionManager" ref="transactionManager"/>
   <property name="transactionAttributes">
     <props>
       <prop key="insert*">PROPAGATION_REQUIRED</prop>
       <prop key="update*">PROPAGATION_REQUIRED</prop>
       <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
     </props>
   </property>
 </bean>

 <bean id="myProxy" parent="baseTransactionProxy">
   <property name="target" ref="myTarget"/>
 </bean>

 <bean id="yourProxy" parent="baseTransactionProxy">
   <property name="target" ref="yourTarget"/>
 </bean>

spring 读取到配置文件的信息时会去解析相关的元素,关于spring bean的解析原理及如何生成bean可参考文章:基于Spring可扩展Schema提供自定义配置支持这里就不再细说。

TransactionProxyFactoryBean类是代理bean工厂,简化事务处理。

public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean
		implements BeanFactoryAware 

继承AbstractSingletonProxyFactoryBean, 该类提供了创建事务bean代理对象的方法。

public void afterPropertiesSet() {
		if (this.target == null) {
			throw new IllegalArgumentException("Property 'target' is required");
		}
		if (this.target instanceof String) {
			throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value");
		}
		if (this.proxyClassLoader == null) {
			this.proxyClassLoader = ClassUtils.getDefaultClassLoader();
		}

		ProxyFactory proxyFactory = new ProxyFactory();

		if (this.preInterceptors != null) {
			for (Object interceptor : this.preInterceptors) {
				proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
			}
		}

		// Add the main interceptor (typically an Advisor).
		proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));

		if (this.postInterceptors != null) {
			for (Object interceptor : this.postInterceptors) {
				proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
			}
		}

		proxyFactory.copyFrom(this);

		TargetSource targetSource = createTargetSource(this.target);
		proxyFactory.setTargetSource(targetSource);

		if (this.proxyInterfaces != null) {
			proxyFactory.setInterfaces(this.proxyInterfaces);
		}
		else if (!isProxyTargetClass()) {
			// Rely on AOP infrastructure to tell us what interfaces to proxy.
			proxyFactory.setInterfaces(
					ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));
		}

		this.proxy = proxyFactory.getProxy(this.proxyClassLoader);/**此处创建了代理对象**/
	}
而在该方法中调用了createMainInterceptor方法,该方法很重要,获取到事务的拦截对象,进入到该方法中:

protected Object createMainInterceptor() {
		this.transactionInterceptor.afterPropertiesSet();
		if (this.pointcut != null) {
			return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
		}
		else {
			// Rely on default pointcut.
			return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);
		}
	}
这样,当我们调用业务bean的处理方法时,实际上是调用代理对象Interceptor的Invoker方法:

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor,Serializable {
 
    public Object invoke(final MethodInvocationinvocation) throws Throwable {
                                                                                                                                                  .......
              //就在这一句开启事务
              TransactionInfotxInfo = createTransactionIfNecessary(tm, txAttr,joinpointIdentification);
              ......
              retVal= invocation.proceed();   //执行下一个拦截器 或 执行代理目标的方法
              ......                                                                                                                                      
              commitTransactionAfterReturning(txInfo);  <span style="font-family: Arial, Helvetica, sans-serif;">//提交事务           </span>
                                                                   
              return retVal;
              .......
    } 
}
该方法中实现了真正的在业务bean方法中加入事务处理,现在我们来分析下这段源码。

我们注意到这段代码:TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification),该代码就决定了是否启用事务处理。深入到该方法内部,

该方法调用了status = tm.getTransaction(txAttr),这里就是获取事务的关键部分。进入该方法的实现:

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
 ......
   public final TransactionStatus getTransaction(TransactionDefinitiondefinition) throws TransactionException {
              </span>
              //这里是取得当前已绑定到TransactionSynchronizationManager的上下文的事务,主要为事务传播行为而设
              Object transaction =doGetTransaction();
              ........
              //如果事务已存在,根据事务传播行为来处理,
              if(isExistingTransaction(transaction)) {
                     // Existingtransaction found -> check propagation behavior to find out how to behave.
                     return handleExistingTransaction(definition, transaction, debugEnabled);
              }
              ......
              //这里最关键,开启一个新的事务,并放进TransactionSynchronizationManager的上下文中,并绑定到当前线程)
              doBegin(transaction,definition);
              return status;
              .......
       }
......
}

AbstractPlatformTransactionManager抽象类是spring事务处理中的一个核心类,该类实现接口PlatformTransactionManager,他们之间的关系如下图示:



如上图所示,spring实现了几种方式的事务处理,其中有JTA,DataSource,Hibernate,JDO,JPA,CCI。现在我们进入HibernateTransactionManager的doGenTransaction的方法内部,查看他是如何处理的,其他的几个都是类似的。

public class HibernateTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {

	protected Object doGetTransaction() {
		HibernateTransactionObject txObject = new HibernateTransactionObject();
		......

		//在TransactionSynchronizationManager的上下文中查找当前的Session(实质上也是与线程绑定的)
		SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());

		......
		return txObject;
	}

}
该方法尝试获取当前已绑定到TransactionSynchronizationManager的上下文的事务,主要为事务传播行为而设定。然后进入doBegin()方法,该方法尝试开启一个新的事务,并放进TransactionSynchronizationManager的上下文(ThreadLocal的Map)中,绑定到当前线程中(线程的ThreadLocal变量中)。

public class HibernateTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
......
     protected void doBegin(Object transaction, TransactionDefinition definition) {
                HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
		.........
		try {
			if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
				//这里才真正的打开Session
				Session newSession = SessionFactoryUtils.openSession(getSessionFactory());
				.........
			}
			session = txObject.getSessionHolder().getSession();
                        .........
			Transaction hibTx;
			// Register transaction timeout.
			.........
			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				.........
			}
			else {
				//这里才真正地开启事务
				hibTx = session.beginTransaction();
			}
			.........
                        //如果这新开启的Session,则将SessionHolder(Session和Transaction)放到TransactionSynchronizationManager的上下文中(绑定到当前线程)
			// Bind the session holder to the thread.
			if (txObject.isNewSessionHolder()) {                                                                                              
                                //以键值对<SessionFactory,SessionHolder>形式绑定到TransactionSynchronizationManager的上下文中
				TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
			}		
			.......
		}
		.........
     }
......
}
主要是理解TransactionSynchronizationManager, 要懂得Spring的TransactionManager开启事务后是以键值对<SessionFactory,SessionHolder>形式 存放到 TransactionSynchronizationManager的上下文(ThreadLocal的Map)中(以ThreadLocal的方式与当前线程绑定)。

在获取Session,开启事务后,又回到TransactionInterceptor 的Invoker方法中,进行实际业务的处理:retVal= invocation.proceed(),处理完之后,则开始提交事务或者回滚事务。
成功后提交事务:commitTransactionAfterReturning(txInfo),进入该方法内部就可发现是调用了PlatformTransactionManager.commin方法进行提交。
失败后回滚事务:completeTransactionAfterThrowing(txInfo, ex)也是类似。
至此Spring的基于动态代理方式实现事务处理的流程就讲完了。






阅读更多
个人分类: Spring MVC
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭