傻瓜式建网站,中国建筑校园招聘官网,wordpress怎么清楚没用的文件,自己做一个网站Spring事务简介
Spring事务有两种方式#xff1a;
编程式事务#xff1a;编程式事务通常使用编程式事务管理API实现#xff0c;比如Spring提供的PlatformTransactionManager接口#xff0c;使用它操控事务。声明式事务#xff1a;注解式事务使用AOP#xff08;面向切面…Spring事务简介
Spring事务有两种方式
编程式事务编程式事务通常使用编程式事务管理API实现比如Spring提供的PlatformTransactionManager接口使用它操控事务。声明式事务注解式事务使用AOP面向切面编程来实现在方法调用前后添加事务处理逻辑。除了XML配置外Spring还支持使用注解来声明事务目前使用注解是更方便和主流的方式。 Spring注解式事务原理
Spring在实例化bean时会将带有Transactional注解的类生成一个代理类对象注入使用这个bean就是使用代理类对象。这个代理类对象的方法拦截器类似Spring AOP的Around把业务方法包裹在事务的开启、事务的提交和事务的回滚从而让代理类拦截器自动处理事务。事务同步管理器将事务状态和信息存储在线程的ThreadLocal里通过取ThreadLocal的事务信息实现方法嵌套调用中的事务信息传递。
以下这张流程图来自Spring官网: Spring事务总览
Spring事务处理有以下几个重要组件 代理对象假设SimpleServiceA是原始类那么在Spring初始化bean时会进行增强生成代理类SimpleServiceA$$EnhancerBySpringCGLIB$$22b9f492的实例代理对象对目标方法进行功能拦截器自动完成事务的开启、提交和回滚。 事务拦截器 TransactionInterceptor事务拦截器将事务管理逻辑与业务代码进行解耦作用类似于Spring AOP的一个拦截器用于在方法调用前后实现事务管理。 事务管理器 PlatformTransactionManager Spring事务管理器负责管理事务的生命周期包括事务的开始、提交或回滚等操作其中最常用的事务管理器实现类是DataSourceTransactionManagerDataSourceTransactionManager除了上述的功能还提供了方法使用数据源去获取和返还数据连接。 事务同步管理器 TransactionSynchronizationManagerSpring 框架中用于管理事务同步的工具类将事务信息和状态和线程绑定。
Spring事务组件关系图 事务有关的信息和状态类
Spring事务在处理流程中有一系列的信息和状态类让人眼花缭乱下面来列举这些类理清它们的关系。
TransactionInfo事务信息包含几乎所有事务信息和状态在源码里简称为txInfo内含TransactionAttribute(事务定义)、TransactionStatus(事务状态)和事务管理器。TransactionAttribute事务定义里面存放着事务属性。TransactionStatus事务状态信息在源码里简称为status实现类为DefaultTransactionStatus内含事务对象DataSourceTransactionObject、savepoint保存点和挂起的数据库连接资源suspendedResources。DataSourceTransactionObject事务对象在源码里简称为txObject或transaction内含数据库连接ConnectionHolder。ConnectionHolder数据库连接持有者持有着数据库连接。 方法嵌套调用的情况下每个事务拦截器进来后都会创建方法自身的TransactionInfo、TransactionStatus、DataSourceTransactionObject。 事务有关的信息和状态类关系图 事务定义类
在事务处理中事务的定义类TransactionDefinition有很多衍生类和接口它们的属性从事务注解Transactional解析而来在原码里名称为txAttr关系如下 其中DelegatingTransactionAttribute的类图 图上那一系列类和接口虽然比较绕但都是和事务的定义有关。
事务对象
事务对象跟踪和管理与事务相关的状态和资源包含数据库连接connectionHolder实现类为DataSourceTransactionObject在源码里简称为txObject或transaction它的类图如下 事务管理器
事务管理器 PlatformTransactionManager 是Spring负责管理事务的生命周期的事务管理器包括事务的开始、提交或回滚等操作通过将事务信息和数据库连接绑定至线程实现多个嵌套方法间的传播。 事务管理器内部存放着数据源DataSource能通过数据源获取和返还数据库连接对事务的处理就是通过数据源的连接连接进行的。 事务管理器实现类有 DataSourceTransactionManager、JtaTransactionManager、WebSphereUowTransactionManager等此处分析的是最常用的实现类DataSourceTransactionManager。
事务管理器类图 Transactional注解
Target({ElementType.METHOD, ElementType.TYPE})
Retention(RetentionPolicy.RUNTIME)
Inherited
Documented
public interface Transactional {AliasFor(transactionManager)String value() default ;AliasFor(value)String transactionManager() default ;Propagation propagation() default Propagation.REQUIRED;Isolation isolation() default Isolation.DEFAULT;int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;boolean readOnly() default false;Class? extends Throwable[] rollbackFor() default {};String[] rollbackForClassName() default {};Class? extends Throwable[] noRollbackFor() default {};String[] noRollbackForClassName() default {};}Target({ElementType.METHOD ElementType.TYPE}): 指定此注解可以应用的位置可以是方法或类型类和接口。
Retention(RetentionPolicy.RUNTIME): 表示此注解应在运行时保留允许在运行时反射检查它。
注解属性
valuetransactionManager的别名和transactionManager的作用一样。transactionManager事务管理器Spring事务支持使用多个事务管理器可以通过该属性使用指定事务管理器。propagation 事务传播方式它的默认值是 Propagation.REQUIRED。readOnly: 指定事务是否为只读默认值是 false。isolation 指定事务的隔离级别默认值是 Isolation.DEFAULT即数据库设定的隔离级别。timeout事务超时时间默认为数据库设定的时间。rollbackFor设定要回滚事务的异常类当捕获到这些异常时回滚否则不回滚。rollbackForClassName设定要回滚事务的异常类名称当捕获到这些异常时回滚否则不回滚。noRollbackFor设定不回滚事务的异常类当捕获到这些异常时不回滚。noRollbackForClassName设定不回滚事务的异常类名称当捕获到这些异常时不回滚。
事务传播方式 Propagation
传播方式备注REQUIRED当前有事务时沿用现有事务不存在的时候新建一个事务是默认传播方式。SUPPORTS当前有事务时沿用现有事务没有的时候不使用事务。MANDATORY当前有事务时沿用现有事务不存在时抛出异常。REQUIRES_NEW创建新事务若存在原有事务则挂起原事务。NOT_SUPPORTED不使用事务若存在原有事务则挂起原事务。NEVER不使用事务若存在原有事务则抛出异常。NESTED开始一个 “嵌套的” 事务, 它是已经存在事务的一个真正的子事务 嵌套事务开始执行时 它将取得一个 savepoint。 如果这个嵌套事务失败 我们将回滚到此 savepoint。嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。
事务隔离级别 Isolation
隔离级别中文名称备注READ_UNCOMMITTED读未提交最低的隔离级别一个事务可以读取另一个事务未提交的数据。可能会导致脏读、幻读或不可重复读。READ_COMMITTED读已提交一个事务只能读取已经提交的数据但是在同一事务中多次读取同一数据可能会得到不同的结果。REPEATABLE_READ可重复读一个事务在同一数据上进行多次读取时可以得到相同的结果但是在同一事务中其他事务插入的数据对该事务不可见。SERIALIZABLE串行化最高的隔离级别所有事务串行执行保证数据的一致性和完整性。 代理类
Spring实例化bean时生成事务增强的代理类如下图的例子SimpleController里的Autowired SimpleService1 simpleService注入bean不是原始的类实例而是一个Spring实例化bean时使用Cglib生成代理类本例里是 SimpleServiceA$$EnhancerBySpringCGLIB$$1577407e。这个代理类继承自SimpleServiceA它的作用是向类增加功能拦截器进行链式处理对事务注解来说就是添加一个TransactionInterceptor增加事务的处理。
这个代理类编译或打包后是搜索不到的在Spring启动后动态生成在Spring应用启动运行时可通过arthas或jad等工具反编译得到。
从这个类的代码可以看到代理类继承原类SimpleServiceA代理类的updateA()对原始updateA()方法进行拦截。
代理类代码
public class SimpleServiceA$$EnhancerBySpringCGLIB$$22b9f492
extends SimpleServiceA
implements SpringProxy,
Advised,
Factory {private boolean CGLIB$BOUND;public static Object CGLIB$FACTORY_DATA;private static final ThreadLocal CGLIB$THREAD_CALLBACKS;private static final Callback[] CGLIB$STATIC_CALLBACKS;private MethodInterceptor CGLIB$CALLBACK_0;private MethodInterceptor CGLIB$CALLBACK_1;private NoOp CGLIB$CALLBACK_2;private Dispatcher CGLIB$CALLBACK_3;private Dispatcher CGLIB$CALLBACK_4;private MethodInterceptor CGLIB$CALLBACK_5;private MethodInterceptor CGLIB$CALLBACK_6;private static Object CGLIB$CALLBACK_FILTER;private static final Method CGLIB$updateA$0$Method;private static final MethodProxy CGLIB$updateA$0$Proxy;private static final Object[] CGLIB$emptyArgs;private static final Method CGLIB$equals$1$Method;private static final MethodProxy CGLIB$equals$1$Proxy;private static final Method CGLIB$toString$2$Method;private static final MethodProxy CGLIB$toString$2$Proxy;private static final Method CGLIB$hashCode$3$Method;private static final MethodProxy CGLIB$hashCode$3$Proxy;private static final Method CGLIB$clone$4$Method;private static final MethodProxy CGLIB$clone$4$Proxy;static {SimpleServiceA$$EnhancerBySpringCGLIB$$22b9f492.CGLIB$STATICHOOK144();SimpleServiceA$$EnhancerBySpringCGLIB$$22b9f492.CGLIB$STATICHOOK143();}static void CGLIB$STATICHOOK144() {try {return;}catch (Error | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}static void CGLIB$STATICHOOK143() {CGLIB$THREAD_CALLBACKS new ThreadLocal();CGLIB$emptyArgs new Object[0];Class? clazz Class.forName(cn.massivestars.service.impl.SimpleServiceA$$EnhancerBySpringCGLIB$$22b9f492);Class? clazz2 Class.forName(java.lang.Object);Method[] methodArray ReflectUtils.findMethods(new String[]{equals, (Ljava/lang/Object;)Z, toString, ()Ljava/lang/String;, hashCode, ()I, clone, ()Ljava/lang/Object;}, clazz2.getDeclaredMethods());CGLIB$equals$1$Method methodArray[0];CGLIB$equals$1$Proxy MethodProxy.create(clazz2, clazz, (Ljava/lang/Object;)Z, equals, CGLIB$equals$1);CGLIB$toString$2$Method methodArray[1];CGLIB$toString$2$Proxy MethodProxy.create(clazz2, clazz, ()Ljava/lang/String;, toString, CGLIB$toString$2);CGLIB$hashCode$3$Method methodArray[2];CGLIB$hashCode$3$Proxy MethodProxy.create(clazz2, clazz, ()I, hashCode, CGLIB$hashCode$3);CGLIB$clone$4$Method methodArray[3];CGLIB$clone$4$Proxy MethodProxy.create(clazz2, clazz, ()Ljava/lang/Object;, clone, CGLIB$clone$4);clazz2 Class.forName(cn.massivestars.service.impl.SimpleServiceA);//原始方法CGLIB$updateA$0$Method ReflectUtils.findMethods(new String[]{updateA, ()V}, clazz2.getDeclaredMethods())[0];//代理方法CGLIB$updateA$0$Proxy MethodProxy.create(clazz2, clazz, ()V, updateA, CGLIB$updateA$0);}}//代理方法和原始方法不一样作了功能增强public final void updateA() throws Exception {try {MethodInterceptor methodInterceptor this.CGLIB$CALLBACK_0;if (methodInterceptor null) {SimpleServiceA$$EnhancerBySpringCGLIB$$22b9f492.CGLIB$BIND_CALLBACKS(this);methodInterceptor this.CGLIB$CALLBACK_0;}if (methodInterceptor ! null) {//使用代理方法对原始方法updateA()进行了功能增强Object object methodInterceptor.intercept(this, CGLIB$updateA$0$Method, CGLIB$emptyArgs, CGLIB$updateA$0$Proxy);return;}//没有功能增强时使用原始方法super.updateA();return;}catch (Error | Exception | RuntimeException throwable) {throw throwable;}catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}//省略代码……
}代理类的生成
Spring在初始化bean实例的时候过检查一系列条件来确定是否需要对 Bean 进行代理比如对有Transactional注解的bean生成额外的增强的代理对象。由于篇幅问题下面的代码分析忽略Spring对一般bean初始化的过程从生成bean的代理对象开始即AbstractAutoProxyCreator#postProcessAfterInitialization()方法开始分析可以跟着这个调用栈跟踪代理对象的生成。 spring bean功能自动代理部分
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupportimplements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean ! null) {Object cacheKey getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {//开始包裹成代理类return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (beanName ! null this.targetSourcedBeans.contains(beanName)) {return bean;}if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}//1、查找需要生成的功能增强Object[] specificInterceptors getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors ! DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);//2、创建代理Object proxy createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}protected Object createProxy(Class? beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}//3、创建类代理工厂ProxyFactory proxyFactory new ProxyFactory();proxyFactory.copyFrom(this);if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {evaluateProxyInterfaces(beanClass, proxyFactory);}}//4、构建增强Advisor[] advisors buildAdvisors(beanName, specificInterceptors);for (Advisor advisor : advisors) {proxyFactory.addAdvisor(advisor);}proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}//5、使用代理工厂创建代理return proxyFactory.getProxy(getProxyClassLoader());}}代理工厂部分
public class ProxyFactory extends ProxyCreatorSupport {public Object getProxy(ClassLoader classLoader) {//6、创建aop代理//7、返回代理对象return createAopProxy().getProxy(classLoader);}protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}//6.1 使用aop工厂创建aop代理return getAopProxyFactory().createAopProxy(this);}}public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {//6.2 创建aop代理public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class? targetClass config.getTargetClass();if (targetClass null) {throw new AopConfigException(TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.);}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}//创建cglib aop代理对象return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}}cglib代理对象部分
class ObjenesisCglibAopProxy extends CglibAopProxy {public ObjenesisCglibAopProxy(AdvisedSupport config) {super(config);}//7.1 返回增强的代理对象public Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug(Creating CGLIB proxy: target source is this.advised.getTargetSource());}try {Class? rootClass this.advised.getTargetClass();Assert.state(rootClass ! null, Target class must be available for creating a CGLIB proxy);//省略代码……//创建增强器Enhancer enhancer createEnhancer();if (classLoader ! null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}//配置增强器enhancer.setSuperclass(proxySuperClass);enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));Callback[] callbacks getCallbacks(rootClass);Class?[] types new Class?[callbacks.length];for (int x 0; x types.length; x) {types[x] callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);//创建代理类并实例化return createProxyClassAndInstance(enhancer, callbacks);}//省略代码...}protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {Class? proxyClass enhancer.createClass();Object proxyInstance null;if (objenesis.isWorthTrying()) {try {//创建对象objenesis创建对象时可以不调用类的构造函数proxyInstance objenesis.newInstance(proxyClass, enhancer.getUseCache());}catch (Throwable ex) {logger.debug(Unable to instantiate proxy using Objenesis, falling back to regular proxy construction, ex);}}//省略代码……((Factory) proxyInstance).setCallbacks(callbacks);return proxyInstance;}}由于篇幅问题对spring aop生成代理对象的内容这里只作简略介绍。 代理类责任链模式处理
Spring的bean可以有多个功能增强Transactional事务处理是其中一种还有Cacheable缓存、Async异步执行和Retryable重试等处理拥有多个功能增强的代理类Spring使用了一种叫责任链的设计模式。
下面是有Transactional、Cacheable和Retryable三个功能增强的责任链 下图为责任链链式处理的调用调用栈 从代理对象到业务方法的过程
从代理对象开始是如何执行到事务拦截器的呢从上面的代理类代码可以看到调用代理类的方法时在有功能增强时实际调用的是MethodInterceptor的intercept(..)方法MethodInterceptor实现类是DynamicAdvisedInterceptor在intercept(..)里获取功能增强责任链如果责任链不为空创建CglibMethodInvocation对象进行处理责任链。
从代理类到业务方法的时序图 private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {private final AdvisedSupport advised;public DynamicAdvisedInterceptor(AdvisedSupport advised) {this.advised advised;}Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy null;boolean setProxyContext false;Class? targetClass null;Object target null;try {if (this.advised.exposeProxy) {oldProxy AopContext.setCurrentProxy(proxy);setProxyContext true;}target getTarget();if (target ! null) {targetClass target.getClass();}//1、获取功能增强责任链ListObject chain this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;if (chain.isEmpty() Modifier.isPublic(method.getModifiers())) {//责任链为空Object[] argsToUse AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal methodProxy.invoke(target, argsToUse);}else {//2、责任链不为空retVal new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target ! null) {releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}}//省略代码……}
}private static class CglibMethodInvocation extends ReflectiveMethodInvocation {//3、处理责任链public Object proceed() throws Throwable {if (this.currentInterceptorIndex this.interceptorsAndDynamicMethodMatchers.size() - 1) {//如果责任链已处理完成调用业务方法return invokeJoinpoint();}//处理责任链的下一个功能增强Object interceptorOrInterceptionAdvice this.interceptorsAndDynamicMethodMatchers.get(this.currentInterceptorIndex);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {InterceptorAndDynamicMethodMatcher dm (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {return proceed();}}else {//调用具体的拦截器return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}
}
下面是一个有Cacheable、Retryable和Transactional注解的调用栈很清晰的展示代理对象功能增强的调用过程
cn.massivestars.service.SimpleServiceA.updateA(SimpleServiceA.java:33)
cn.massivestars.service.SimpleServiceA$$FastClassBySpringCGLIB$$6479dd5.invoke(generated)
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:280)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.cache.interceptor.CacheInterceptor$1.invoke(CacheInterceptor.java:52)
org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:345)
org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:414)
org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:327)
org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.retry.interceptor.RetryOperationsInterceptor$1.doWithRetry(RetryOperationsInterceptor.java:74)
org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:276)
org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:157)
org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:101)
org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:118)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
cn.massivestars.service.SimpleServiceA$$EnhancerBySpringCGLIB$$3b7e878d.updateA(generated)
cn.massivestars.controller.SimpleController.update(SimpleController.java:28)事务处理的核心方法
事务的处理和我们自己手写的类似使用try catch代码块包裹业务方法在业务方法前开启事务捕获异常时回滚事务正常运行时最后提交事务。
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {//事务关键代码//这个方法继承自TransactionAspectSupport代码在TransactionAspectSupportprotected Object invokeWithinTransaction(Method method, Class? targetClass, final InvocationCallback invocation)throws Throwable {final TransactionAttribute txAttr getTransactionAttributeSource().getTransactionAttribute(method, targetClass);final PlatformTransactionManager tm determineTransactionManager(txAttr); //取事务管理器final String joinpointIdentification methodIdentification(method, targetClass);if (txAttr null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { //如果必要创建事务TransactionInfo txInfo createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal null;try {//责任链的下一个拦截处理器在最后一个拦截器处理完后就是业务代码retVal invocation.proceedWithInvocation(); }catch (Throwable ex) {//出现异常回滚事务completeTransactionAfterThrowing(txInfo, ex); throw ex;}finally {//还原为原来的事务信息txInfocleanupTransactionInfo(txInfo);}//提交事务commitTransactionAfterReturning(txInfo);return retVal;}//省略代码……}}有关的类和组件都已经介绍完毕下面看看事务管理器处理事务的开始、提交和回滚是怎样实现。 开始事务
开始事务流程如下
创建一个事务对象DataSourceTransactionObject其名称为transaction将事务对象关联线程绑定的数据库连接(ConnectionHolder)如果线程没有绑定的连接那么原来就是没有存在事务该事务对象状态为新。根据事务对象transaction判断是不是已存在事务根据原来是否已经存在事务作2种不同的处理方式。
存在事务根据事务的传播方式作不同处理
PROPAGATION_NEVER抛出异常。PROPAGATION_NOT_SUPPORTED不作事务处理。PROPAGATION_REQUIRES_NEW使用新的数据库连接开启新事务B将B的事务信息和状态绑定到线程同时挂起原来的事务A在新事务B完成后线程绑定的事务信息恢复为原事务A。PROPAGATION_NESTED开始一个 “嵌套的” 事务, 它是已经存在事务的一个真正的子事务 嵌套事务开始执行时它将取得一个 savepoint。如果这个嵌套事务失败 将回滚到此 savepoint。嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。
不存在事务根据事务的传播方式作不同处理
PROPAGATION_MANDATORY抛出异常事务拦截器捕抓异常后回滚事务结束事务处理。PROPAGATION_REQUIRED | PROPAGATION_REQUIRES_NEW | PROPAGATION_NESTED从数据源获取连接开启事务将事务信息和状态绑定到线程。其它事务传播方式创建空事务对象不真正去处理事务只是将事务信息和状态绑定到线程。
事务开启完成后配制事务信息TransactionInfo txInfo将当前方法事务信息绑定到线程并保留原事务信息以便方法嵌套调用的时候可以恢复。
开始事务源码事务拦截器部分
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor {protected TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {//如果事务有名称将txAttr替换成有事务名称的DelegatingTransactionAttribute实例(相比原来的类多了事务名称)if (txAttr ! null txAttr.getName() null) {txAttr new DelegatingTransactionAttribute(txAttr) {Overridepublic String getName() {return joinpointIdentification;}};}TransactionStatus status null;if (txAttr ! null) {if (tm ! null) {//如果事务管理器不为null开启事务status tm.getTransaction(txAttr);}}//配制事务信息事务信息txInfo绑定至当前线程return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);}protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {TransactionInfo txInfo new TransactionInfo(tm, txAttr, joinpointIdentification);if (txAttr ! null) {txInfo.newTransactionStatus(status);}// 即使在这里没有创建新的事务始终将 TransactionInfo 绑定到线程。// 这确保了即使没有由此切面创建事务TransactionInfo 堆栈也将被正确管理。txInfo.bindToThread();return txInfo;}protected final class TransactionInfo {private void bindToThread() {//绑定当前方法事务信息保留原来事务信息以便当前方法事务结束后恢复this.oldTransactionInfo transactionInfoHolder.get();transactionInfoHolder.set(this);}}//省略代码...
}开始事务源码事务管理器部分
public class DataSourceTransactionManager extends AbstractPlatformTransactionManagerimplements ResourceTransactionManager, InitializingBean {//数据源private DataSource dataSource;//此方法继承自AbstractPlatformTransactionManager代码在AbstractPlatformTransactionManagerpublic final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {//创建一个新的事务对象transaction//如果线程已存在事务事务对象transaction使用原有的连接Object transaction doGetTransaction();if (definition null) {definition new DefaultTransactionDefinition();}if (isExistingTransaction(transaction)) {//存在事务根据事务的传播方式作不同处理return handleExistingTransaction(definition, transaction, debugEnabled);}//省略代码...//以下代码为不存在事务时的处理if (definition.getPropagationBehavior() TransactionDefinition.PROPAGATION_MANDATORY) {//如果事务传播方式为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);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 {//创建空事务对象不真正去处理事务只是将事务信息和状态绑定到线程boolean newSynchronization (getTransactionSynchronization() SYNCHRONIZATION_ALWAYS);return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);}}protected Object doGetTransaction() {DataSourceTransactionObject txObject new DataSourceTransactionObject();txObject.setSavepointAllowed(isNestedTransactionAllowed());ConnectionHolder conHolder (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);txObject.setConnectionHolder(conHolder, false); //将事务对象内的数据库连接设置为线程绑定的那个return txObject;}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();txObject.setConnectionHolder(new ConnectionHolder(newCon), true);}txObject.getConnectionHolder().setSynchronizedWithTransaction(true);con txObject.getConnectionHolder().getConnection();//设置事务隔离级别Integer previousIsolationLevel DataSourceUtils.prepareConnectionForTransaction(con, definition);txObject.setPreviousIsolationLevel(previousIsolationLevel);//如果设置了事务自动提交改为手动提交if (con.getAutoCommit()) {txObject.setMustRestoreAutoCommit(true);con.setAutoCommit(false);}txObject.getConnectionHolder().setTransactionActive(true);//设置事务超时时间int timeout determineTimeout(definition);if (timeout ! TransactionDefinition.TIMEOUT_DEFAULT) {txObject.getConnectionHolder().setTimeoutInSeconds(timeout);}//将数据库连接绑定到线程if (txObject.isNewConnectionHolder()) {TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());}}catch (Throwable ex) {//如果出现异常归还还数据库连接if (txObject.isNewConnectionHolder()) {DataSourceUtils.releaseConnection(con, this.dataSource);txObject.setConnectionHolder(null, false);}throw new CannotCreateTransactionException(Could not open JDBC Connection for transaction, ex);}}
}挂起事务
嵌套事务是指在一个事务内部开启了另一个事务。当一个事务内部开启了另一个事务时外部事务会暂时挂起直到内部事务执行完成。在源码中多次出现suspend()方法挂起原事务挂起事务的目的在于
支持嵌套事务在某些事务传播行为下比如PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTEDSpring需要支持嵌套事务。当这些传播行为发生时当前正在执行的事务可能需要被挂起以便开始一个新的事务。挂起原事务可以暂时中断当前事务的执行让新的事务能够开始执行。
保存原事务的状态挂起原事务会保存原事务的状态信息以便在新事务执行完毕后能够正确地恢复原事务的状态。这对于事务管理的一致性和可靠性非常重要。
处理事务异常在执行新事务的过程中可能会发生异常。挂起原事务可以确保异常的发生不会影响到原事务的状态保证事务的正确回滚和异常处理。
挂起事务的有关源码:
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager {//该方法继承自父类AbstractPlatformTransactionManager代码在父类AbstractPlatformTransactionManagerprotected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {if (TransactionSynchronizationManager.isSynchronizationActive()) {ListTransactionSynchronization suspendedSynchronizations doSuspendSynchronization();try {Object suspendedResources null; //挂起的数据库连接持有者 if (transaction ! null) {suspendedResources doSuspend(transaction); //挂起事务}//将线程绑定的原事务信息清除返回原事务信息作为挂起事务信息String name TransactionSynchronizationManager.getCurrentTransactionName();TransactionSynchronizationManager.setCurrentTransactionName(null);boolean readOnly TransactionSynchronizationManager.isCurrentTransactionReadOnly();TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);Integer isolationLevel TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);boolean wasActive TransactionSynchronizationManager.isActualTransactionActive();TransactionSynchronizationManager.setActualTransactionActive(false);return new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);}catch (RuntimeException ex) {//还原事务管理器注册的TransactionSynchronization对象doResumeSynchronization(suspendedSynchronizations);throw ex;}catch (Error err) {//还原事务管理器注册的TransactionSynchronization对象doResumeSynchronization(suspendedSynchronizations);throw err;}}else if (transaction ! null) {// Transaction active but no synchronization active.Object suspendedResources doSuspend(transaction);return new SuspendedResourcesHolder(suspendedResources);}else {// Neither transaction nor synchronization active.return null;}}//将事务对象的数据库连接设置为空将线程绑定的数据库连接解绑protected Object doSuspend(Object transaction) {DataSourceTransactionObject txObject (DataSourceTransactionObject) transaction;txObject.setConnectionHolder(null);ConnectionHolder conHolder (ConnectionHolder)TransactionSynchronizationManager.unbindResource(this.dataSource);return conHolder;}}恢复事务
上面介绍了事务的挂起既然有挂起就有恢复挂起事务是和恢复事务配套使用的在事务的提交processCommit()和回滚processRollback()的finally代码块都会执行cleanupAfterCompletion()方法这个方法里如果存在挂起的事务信息时会恢复挂起的事务。
恢复事务的有关源码:
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager {implements ResourceTransactionManager, InitializingBean {private void cleanupAfterCompletion(DefaultTransactionStatus status) {status.setCompleted();if (status.isNewSynchronization()) {TransactionSynchronizationManager.clear();}if (status.isNewTransaction()) {doCleanupAfterCompletion(status.getTransaction());}if (status.getSuspendedResources() ! null) {//恢复事务resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());}}protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder)throws TransactionException {if (resourcesHolder ! null) {Object suspendedResources resourcesHolder.suspendedResources;if (suspendedResources ! null) {//恢复旧连接绑定至线程doResume(transaction, suspendedResources);}//恢复事务状态和信息ListTransactionSynchronization suspendedSynchronizations resourcesHolder.suspendedSynchronizations;if (suspendedSynchronizations ! null) {TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);doResumeSynchronization(suspendedSynchronizations);}}}
}public class DataSourceTransactionManager extends AbstractPlatformTransactionManagerimplements ResourceTransactionManager, InitializingBean {protected void doResume(Object transaction, Object suspendedResources) {ConnectionHolder conHolder (ConnectionHolder) suspendedResources;//重新将原数据库连接绑定到线程TransactionSynchronizationManager.bindResource(this.dataSource, conHolder);}}下面来看看事务挂起和恢复的详细过程。假设有代理对象A和代理对象B
代理对象A的注解为Transactional代理对象B的注解为Transactional(propagation Propagation.REQUIRES_NEW)
当调用代理对象A的方法a()时方法a()嵌套调用了代理对象B的方法b()这时候会产生事务的挂起和恢复。
挂起和恢复事务的时序图 提交事务
Spring提交通过事务管理器提交事务通过事务对象txObject内含的数据库连接提交事务在提交事务完成后将做下列操作
事务状态设置为已完成。解绑线程的数据库连接。清除线程绑定的事务状态和信息。重置为旧事务信息TransactionInfo方法嵌套调用的时候。如果事务状态为新事务将数据库连接归还连接池。
事务提交调用栈 源码:
//事务拦截器
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor//该方法继承子类TransactionAspectSupportprotected void commitTransactionAfterReturning(TransactionInfo txInfo) {if (txInfo ! null txInfo.hasTransaction()) {//通过事务管理器提交事务txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}}protected void cleanupTransactionInfo(TransactionInfo txInfo) {if (txInfo ! null) {//恢复为旧的事务信息方法嵌套调用会还原为调用栈中上一个方法的事务信息txInfo.restoreThreadLocalStatus();}}protected final class TransactionInfo {private void restoreThreadLocalStatus() {//恢复为旧的事务信息方法嵌套调用会还原为调用栈中上一个方法的事务信息transactionInfoHolder.set(this.oldTransactionInfo);}}//省略代码……}//事务管理器
public class DataSourceTransactionManager extends AbstractPlatformTransactionManagerpublic final void commit(TransactionStatus status) throws TransactionException {//如果事务状态为已完成抛出异常if (status.isCompleted()) {throw new IllegalTransactionStateException(Transaction is already completed - do not call commit or rollback more than once per transaction);}DefaultTransactionStatus defStatus (DefaultTransactionStatus) status;if (defStatus.isLocalRollbackOnly()) {processRollback(defStatus);return;}if (!shouldCommitOnGlobalRollbackOnly() defStatus.isGlobalRollbackOnly()) {processRollback(defStatus);if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {throw new UnexpectedRollbackException(Transaction rolled back because it has been marked as rollback-only);}return;}processCommit(defStatus); //处理事务提交}//该方法继承子类AbstractPlatformTransactionManagerprivate void processCommit(DefaultTransactionStatus status) throws TransactionException {try {boolean beforeCompletionInvoked false;try {prepareForCommit(status);//调用业务方法里注册TransactionSynchronization对象的beforeCommit()方法triggerBeforeCommit(status);//调用业务方法里注册TransactionSynchronization对象的beforeCompletion()方法triggerBeforeCompletion(status); beforeCompletionInvoked true;boolean globalRollbackOnly false;if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {globalRollbackOnly status.isGlobalRollbackOnly();}//释放在当前事务中之前定义的一个保存点。if (status.hasSavepoint()) {status.releaseHeldSavepoint();}else if (status.isNewTransaction()) {//如果是事务状态为新事务才提交(方法嵌套调用的话是在最外层的方法)doCommit(status);}// Throw UnexpectedRollbackException if we have a global rollback-only// marker but still didnt get a corresponding exception from commit.if (globalRollbackOnly) {throw new UnexpectedRollbackException(Transaction silently rolled back because it has been marked as rollback-only);}}catch (UnexpectedRollbackException ex) {//调用业务方法里注册TransactionSynchronization对象的afterCompletion()方法triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);throw ex;}catch (TransactionException ex) {// can only be caused by doCommitif (isRollbackOnCommitFailure()) {doRollbackOnCommitException(status, ex);}else {//调用业务方法里注册TransactionSynchronization对象的afterCompletion()方法triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);}throw ex;}catch (RuntimeException ex) {if (!beforeCompletionInvoked) {//调用业务方法里注册TransactionSynchronization对象的beforeCompletion()方法triggerBeforeCompletion(status);}doRollbackOnCommitException(status, ex);throw ex;}catch (Error err) {if (!beforeCompletionInvoked) {//调用业务方法里注册TransactionSynchronization对象的beforeCompletion()方法triggerBeforeCompletion(status);}doRollbackOnCommitException(status, err);throw err;}try {//调用业务方法里注册TransactionSynchronization对象的afterCommit()方法triggerAfterCommit(status);}finally {//调用业务方法里注册TransactionSynchronization对象的afterCommit()方法triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);}}finally {cleanupAfterCompletion(status);}}protected void doCommit(DefaultTransactionStatus status) {DataSourceTransactionObject txObject (DataSourceTransactionObject) status.getTransaction();Connection con txObject.getConnectionHolder().getConnection();try {con.commit(); //使用数据库连接提交事务}catch (SQLException ex) {throw new TransactionSystemException(Could not commit JDBC transaction, ex);}}private void cleanupAfterCompletion(DefaultTransactionStatus status) {status.setCompleted(); //事务状态设置为已完成if (status.isNewSynchronization()) {TransactionSynchronizationManager.clear();}if (status.isNewTransaction()) {doCleanupAfterCompletion(status.getTransaction());}if (status.getSuspendedResources() ! null) {//如果是嵌套方法恢复原来挂起的事务resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());}}protected void doCleanupAfterCompletion(Object transaction) {DataSourceTransactionObject txObject (DataSourceTransactionObject) transaction;//解绑线程已绑定的数据库连接if (txObject.isNewConnectionHolder()) {TransactionSynchronizationManager.unbindResource(this.dataSource);}//重置数据库连接的设置Connection con txObject.getConnectionHolder().getConnection();try {if (txObject.isMustRestoreAutoCommit()) {con.setAutoCommit(true);}DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());}catch (Throwable ex) {logger.debug(Could not reset JDBC Connection after transaction, ex);}if (txObject.isNewConnectionHolder()) {//返还数据库连接DataSourceUtils.releaseConnection(con, this.dataSource);}txObject.getConnectionHolder().clear();}}回滚事务
在业务逻辑执行过程中出现异常时事务拦截器会捕获异常并根据事务注解的配置判断是否符合回滚的条件若符合则会回滚事务。 protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {if (txInfo ! null txInfo.hasTransaction()) {if (txInfo.transactionAttribute.rollbackOn(ex)) { //根据规则判断是否要回滚try {//使用事务管理器回滚事务txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());}catch (TransactionSystemException ex2) {ex2.initApplicationException(ex);throw ex2;}catch (RuntimeException ex2) {throw ex2;}catch (Error err) {throw err;}}else {//使用事务管理器提交事务try {txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}catch (TransactionSystemException ex2) {ex2.initApplicationException(ex);throw ex2;}catch (RuntimeException ex2) {throw ex2;}catch (Error err) {logger.error(Application exception overridden by commit error, ex);throw err;}}}}private void processRollback(DefaultTransactionStatus status) {try {try {triggerBeforeCompletion(status);if (status.hasSavepoint()) {status.rollbackToHeldSavepoint();}else if (status.isNewTransaction()) {//如果事务状态为新事务才回滚比如嵌套调用的最外层方法doRollback(status);}else if (status.hasTransaction()) {if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {doSetRollbackOnly(status);}}}catch (RuntimeException ex) {triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);throw ex;}catch (Error err) {triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);throw err;}triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);}finally {cleanupAfterCompletion(status);}}protected void doRollback(DefaultTransactionStatus status) {DataSourceTransactionObject txObject (DataSourceTransactionObject) status.getTransaction();Connection con txObject.getConnectionHolder().getConnection();try {con.rollback(); //使用数据库连接回滚事务}catch (SQLException ex) {throw new TransactionSystemException(Could not roll back JDBC transaction, ex);}
}回滚规则的判断
判断当前异常是否符合注解Transactional设置的rollbackFor和noRollbackFor只有符合条件的异常才回滚事务。
public class RuleBasedTransactionAttribute extends DefaultTransactionAttribute {public boolean rollbackOn(Throwable ex) {RollbackRuleAttribute winner null;int deepest Integer.MAX_VALUE;//是否命中回滚规则if (this.rollbackRules ! null) {for (RollbackRuleAttribute rule : this.rollbackRules) {int depth rule.getDepth(ex);if (depth 0 depth deepest) {deepest depth;winner rule;}}}//如果没有命中回滚规则使用父类的默认回滚规则if (winner null) {return super.rollbackOn(ex);}//不是非回滚规则return !(winner instanceof NoRollbackRuleAttribute);}//该方法继承自DefaultTransactionAttribute代码在DefaultTransactionAttributepublic boolean rollbackOn(Throwable ex) {//默认回滚的异常类型RuntimeException和Errorreturn (ex instanceof RuntimeException || ex instanceof Error);}
}从源码可知默认回滚的异常类型为RuntimeException和Error当出现IOException、NoClassDefFoundException之类的非RuntimeException异常时默认情况事务并不会回滚这可能会导致和我们预期的不一致。大多数情况下推荐事务注解配置rollbackFor的回滚异常为Exception.class。
Transactional(rollbackFor Exception.class)事务完成后清理的方法
Spring在事务提交或回滚后使用cleanupAfterCompletion()方法在事务完成后执行一些必要的清理操作以确保下一个事务可以从一个干净的状态开始。
//事务管理器
public class DataSourceTransactionManager extends AbstractPlatformTransactionManagerprivate void cleanupAfterCompletion(DefaultTransactionStatus status) {status.setCompleted(); //事务状态设置为已完成if (status.isNewSynchronization()) {TransactionSynchronizationManager.clear();}if (status.isNewTransaction()) {doCleanupAfterCompletion(status.getTransaction());}if (status.getSuspendedResources() ! null) {//如果是嵌套方法恢复原来挂起的事务resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());}}protected void doCleanupAfterCompletion(Object transaction) {DataSourceTransactionObject txObject (DataSourceTransactionObject) transaction;//解绑线程已绑定的数据库连接if (txObject.isNewConnectionHolder()) {TransactionSynchronizationManager.unbindResource(this.dataSource);}//重置数据库连接的设置Connection con txObject.getConnectionHolder().getConnection();try {if (txObject.isMustRestoreAutoCommit()) {con.setAutoCommit(true);}DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());}catch (Throwable ex) {logger.debug(Could not reset JDBC Connection after transaction, ex);}if (txObject.isNewConnectionHolder()) {//返还数据库连接DataSourceUtils.releaseConnection(con, this.dataSource);}txObject.getConnectionHolder().clear();}}事务同步管理器TransactionSynchronizationManager
Spring 的事务同步管理器 TransactionSynchronizationManager 是 Spring 框架中用于管理事务同步的工具类。它使用ThreadLocal存储信息允许在事务的不同阶段注册回调以执行特定的操作。主要作用包括以下几个方面
事务同步回调注册 TransactionSynchronizationManager允许在事务的不同阶段注册回调方法如在事务完成时、事务回滚时、事务提交前等。开发者可以通过该工具类注册相应的回调方法来执行特定的操作例如在事务提交后清理资源、发送消息等。
线程绑定 TransactionSynchronizationManager是基于线程的它允许将事务同步回调与当前线程进行绑定。这意味着只有与事务关联的线程才能触发事务同步回调从而保证了线程安全性。
支持多个同步回调 TransactionSynchronizationManager支持注册多个事务同步回调这些回调可以按照注册的顺序执行。这样可以方便地实现多个模块间的协作每个模块都可以在适当的时候执行自己的逻辑。
提供事务状态管理 TransactionSynchronizationManager还提供了方法来获取当前事务的状态如事务是否处于激活状态、是否已经完成、是否已经回滚等。这样可以帮助开发者根据当前事务的状态执行相应的操作。
与事务管理器配合使用 TransactionSynchronizationManager 通常与事务管理器如 PlatformTransactionManager配合使用以确保事务同步回调的正确执行。它可以在事务的开始、提交、回滚等关键节点触发相应的回调并在合适的时机执行事务同步逻辑。
线程绑定的信息
public abstract class TransactionSynchronizationManager {//数据库连接持有者connectionHolderprivate static final ThreadLocalMapObject, Object resources new NamedThreadLocalMapObject, Object(Transactional resources);//在业务方法里通过TransactionSynchronizationManager#registerSynchronization注册的同步执行方法private static final ThreadLocalSetTransactionSynchronization synchronizations new NamedThreadLocalSetTransactionSynchronization(Transaction synchronizations);//业务名称private static final ThreadLocalString currentTransactionName new NamedThreadLocalString(Current transaction name);//事务是否只读private static final ThreadLocalBoolean currentTransactionReadOnly new NamedThreadLocalBoolean(Current transaction read-only status);//业务隔离级别private static final ThreadLocalInteger currentTransactionIsolationLevel new NamedThreadLocalInteger(Current transaction isolation level);//事务是否激活private static final ThreadLocalBoolean actualTransactionActive new NamedThreadLocalBoolean(Actual transaction active);}绑定和解绑资源 这里的资源是指数据库连接持有者。 public static void bindResource(Object key, Object value) throws IllegalStateException {Object actualKey TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);Assert.notNull(value, Value must not be null);MapObject, Object map resources.get();//如果绑定的map对象为空初始化它if (map null) {map new HashMapObject, Object();resources.set(map);}Object oldValue map.put(actualKey, value);// Transparently suppress a ResourceHolder that was marked as void...if (oldValue instanceof ResourceHolder ((ResourceHolder) oldValue).isVoid()) {oldValue null;}if (oldValue ! null) {throw new IllegalStateException(Already value [ oldValue ] for key [ actualKey ] bound to thread [ Thread.currentThread().getName() ]);}}public static Object unbindResource(Object key) throws IllegalStateException {Object actualKey TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);Object value doUnbindResource(actualKey);if (value null) {throw new IllegalStateException(No value for key [ actualKey ] bound to thread [ Thread.currentThread().getName() ]);}return value;}private static Object doUnbindResource(Object actualKey) {MapObject, Object map resources.get();if (map null) {return null;}Object value map.remove(actualKey);if (map.isEmpty()) {resources.remove(); //清除线程绑定的数据库连接}//连接为无效时将它设置为空if (value instanceof ResourceHolder ((ResourceHolder) value).isVoid()) {value null;}return value;} 事务失效
在Spring出现事务失效最常见的是因为在同一个类内部的方法之间的调用在上面已经分析过只有在使用代理对象调用业务方法才会有对应的功能增强同一个类内方法间用的是this对象不具备事务增强。
下面是一个失效例子
Service
public class Caller {AutowiredSimpleService simpleService;public void call() {simpleService.updateA();}
}Service
public class SimpleService {public void updateA() {//这里调用updateB()等同于this.updateB()使用的是this对象不具备事务增强事务失效updateB();}Transactional(rollbackFor Exception.class)public void updateB() {String sql update article set title Today is a good day! where id 1;jdbcTemplate.update(sql);}
}
小结
本文简述了Spring注解式事务Transactional的原理分析了关键代码了解源码的实现能帮助我们更好的使用。