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的基于动态代理方式实现事务处理的流程就讲完了。