Spring事务的基础知识
1、注解相关属性
@Transactional 注解的属性信息
name 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器
propagation 事务的传播行为,默认值为 REQUIRED。
isolation 事务的隔离度,默认值采用 DEFAULT。
timeout 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
read-only 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
rollback-for 用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。
no-rollback- for 抛出 no-rollback-for 指定的异常类型,不回滚事务。
除此以外,@Transactional 注解也可以添加到类级别上。当把@Transactional 注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。见清单 2,EmployeeService 的所有方法都支持事务并且是只读。当类级别配置了@Transactional,方法级别也配置了@Transactional,应用程序会以方法级别的事务属性信息来管理事务,换言之,方法级别的事务属性信息会覆盖类级别的相关配置信息。
2、传播级别
介绍
Spring事务的传播级别描述的是多个使用了@Transactional注解的方法互相调用时,Spring对事务的处理。包涵的传播级别有:(在TransactionDefinition接口中定义)
7种事务传播行为如下:默认 propagation = PROPAGATION_REQUIRED
1.PROPAGATION_REQUIRED
如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,这是最常见的选择,也是Spring默认的事务传播行为。
2.PROPAGATION_SUPPORTS
支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
如果外围事务回滚,内部事务也要回滚。
3.PROPAGATION_MANDATORY
支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4.PROPAGATION_REQUIRES_NEW
创建新事务,无论当前存不存在事务,都创建新事务。
5.PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
7.PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
一、Spring事务开启入口
开启Spring事务很简单,首先在启动类上添加@EnableTransactionManagement注解,再注入一个PlatformTransactionManager事务管理器即可。
@Bean
public DataSourceTransactionManager dataSourceTransactionManager() {
return new DataSourceTransactionManager(dataSource());
}
在开启了Spring事务功能,只需要在事务方法上加上@Transactional注解,该方法就会被Spring当作事务方法来处理,发生异常时自动回滚,无异常时自动提交事务。
1.1 @EnableTransactionManagement
@EnableTransactionManagement注解通过@Import引入了另一个配置TransactionManagentConfigurationSelector。
TransactionManangementConfigurationSelector在Spring中,Selector通常都是用来选择一些Bean,向容器注册BeanDefinition的(严格意义上Selector仅时选择过程,注册的具体过程是在ConfigurationClasspathPostProcessor解析时,调用ConfigurationClassParser触发)。主要的逻辑就是根据代理模式,注册不同的BeanDefinition。对Proxy的模式而言,注入的有两个:
AutoProxyRegistrar,ProxyTransactionManagementConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 开启Spring事务支持
// 通过@EnableTransactionManagement引入TransactionManagementConfigurationSelector组件,进而导入两个bean:
// a、AutoProxyRegistrar
// b、ProxyTransactionManagementConfiguration
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
/**
* 使用JDK动态代理还是Cglib动态代理,默认是false,但前提是AdviceMode必须是PROXY才适用
*/
boolean proxyTargetClass() default false;
/**
* 通知的模式,默认是PROXY,还有一种是ASPECTJ
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* 指定通知器的执行顺序
*/
int order() default Ordered.LOWEST_PRECEDENCE;
}
TransactionManagementConfigurationSelector是ImportSelector的子类,所以它必须重写ImportSelector#selectImports()方法,Spring会自动注册该方法返回的bean集合。
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[]{
AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[]{determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
ransactionManagementConfigurationSelector类的目的主要是向Spring容器注册了两个bean:
1、AutoProxyRegistrar
往容器内注册InfrastructureAdvisorAutoProxyCreator非常关键的bean,基于Advisor创建bean代理对象,让bean拥有事务增强的能力。这个类之前在aop中介绍过,是bean后置处理器,会拦截所有bean的创建,对符合条件的bean创建代理。
总结就是:AutoProxyRegistrar的作用就是启用spring aop的功能,对符合条件的bean创建代理
2、ProxyTransactionManagementConfiguration
往容器内注册BeanFactoryTransactionAttributeSourceAdvisor以及依赖的bean,织入该Advisor的bean将拥有事务增强的能力。
总结就是在aop中添加事务拦截器TransactionInterceptor
由此可见,Spring事务是基于AOP实现的。AutoProxyRegistrar用来创建bean的代理对象,ProxyTransactionManagementConfiguration用来注册事务增强器。二者结合起来的效果就是:对@Transaction标注的bean创建代理对象,代理对象中通过TransactionInterceptor拦截器来实现事务管理的功能。
1.1.1 AutoProxyRegistrar
Registrar同样也是用来向容器注册Bean的,在Proxy的模式下,它会调用AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);向容器中注册InfrastructureAdvisorAutoProxyCreator。而这个类就是之前提到的AbstractAdvisorAutoProxyCreator的子类。
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
@Override
// org.springframework.context.annotation.AutoProxyRegistrar.registerBeanDefinitions
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
// 获取注解的属性
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
// 模式
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
// 注册自动代理创建器:InfrastructureAdvisorAutoProxyCreator
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
logger.info(String.format("%s was imported but no annotations were found " +
"having both 'mode' and 'proxyTargetClass' attributes of type " +
"AdviceMode and boolean respectively. This means that auto proxy " +
"creator registration and configuration may not have occurred as " +
"intended, and components may not be proxied as expected. Check to " +
"ensure that %s has been @Import'ed on the same class where these " +
"annotations are declared; otherwise remove the import of %s " +
"altogether.", name, name, name));
}
}
}
// org.springframework.aop.config.AopConfigUtils#registerAutoProxyCreatorIfNecessary
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 注册或者升级InfrastructureAdvisorAutoProxyCreator组件
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
a、 InfrastructureAdvisorAutoProxyCreator
主要作用是基于容器内的Advisor给需要被增强的bean创建代理对象。
它通过实现BeanPostProcessor接口,重写postProcessAfterInitialization()方法来增强bean,这个逻辑和AOP是一样的。
1.1.2 补充:如何判读是否需要被增强?
连接点是否需要被增强,是通过切点(Pointcut)来判断的,所以PointcutAdvisor接口会关联一个Pointcut
public interface PointcutAdvisor extends Advisor {
/**
* 获取切点,判断方法是否要增强
*/
Pointcut getPointcut();
}
Pointcut用来判断方法是否需要被增强,所以会关联一个类过滤器ClassFilter和方法匹配器MethodMatcher:
public interface Pointcut {
/**
* 先匹配类
*/
ClassFilter getClassFilter();
/**
* 再匹配方法
*/
MethodMatcher getMethodMatcher();
Pointcut TRUE = TruePointcut.INSTANCE;
}
事务增强器是BeanFactoryTransactionAttributeSourceAdvisor类,它本身肯定是一个Advisor,所以也会关联一个Pointcut:
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
它关联的是TransactionAttributeSourcePointcut,默认所有Class都通过,只判断方法是否加了@Transaction注解。
/**
* 目标类的给定方法,是否可以应用事务增强器?
* 条件:方法事务属性不为空,方法事务属性就是通过解析@Transaction注解获取的
* @see AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class, boolean)
*/
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (TransactionalProxy.class.isAssignableFrom(targetClass) ||
PlatformTransactionManager.class.isAssignableFrom(targetClass) ||
PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
1.1.3 补充:增强的切入点规则判断的时机?
就是判断方法是否具有事务属性TransactionAttribute,即是否加了@Transaction注解。这个切点规则是在哪里触发的呢???Spring AOP判断bean是否需要被增强,是通过AbstractAdvisorAutoProxyCreator#findEligibleAdvisors()查找bean是否有可用的Advisor来判断的。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
/**
* 查找容器内所有的Advisor:@Aspect类里定义的各种增强方法
*/
List<Advisor> candidateAdvisors = findCandidateAdvisors();
/**
* 根据切点表达式,过滤出可以应用到beanClass的Advisor
*/
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
/**
* 将ExposeInvocationInterceptor拦截器插入到第一个
* @see ExposeInvocationInterceptor
*/
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
先获取容器内所有的Advisor,再遍历Advisor和bean是否匹配,这个匹配过程就是通过Advisor.Pointcut切点来判断的,方法是AopUtils#canApply()
1.1.4 ProxyTransactionManagementConfiguration
ProxyTransactionManagementConfiguration是一个配置类,如果算上其继承的父类一共是声明了四个类:
1、TransactionalEventListenerFactory
2、BeanFactoryTransactionAttributeSourceAdvisor
3、TransactionAttributeSource
4、TransactionInterceptor
后三个类相对比较重要,我们一一分析。
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
/**
* 注册BeanFactoryTransactionAttributeSourceAdvisor增强器
*/
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
// 注册BeanFactoryTransactionAttributeSourceAdvisor增强器,beanName = "org.springframework.transaction.config.internalTransactionAdvisor"
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
/**
* 注册TransactionAttributeSource,类型是AnnotationTransactionAttributeSource
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
/**
* 注册TransactionInterceptor,实现了MethodInterceptor接口,主要用于拦截事务方法的执行
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
a、BeanFactoryTransactionAttributeSourceAdvisor
BeanFactoryTransactionAttributeSourceAdvisor:
事务增强器包含Pointcut和Advise。
其中的Pointcut是TransactionAttributeSourcePointcut,主要是一些filter和matches之类的方法,用来匹配被代理类。
而Adivise就是我们之后要介绍的TransactionInterceptor。
Spring AOP基于它给bean创建代理对象,让bean拥有事务增强的能力。本身不具备事务能力,依赖TransactionInterceptor。
b、TransactionAttributeSource
TransactionAttributeSource只是一个接口,扩展了TransactionDefinition,增加了isCandidateClass()的方法(可以用来帮助Pointcut匹配)。
这里使用的具体实现是AnnotationTransactionAttributeSource。因为注解式事务候选类(即要被代理的类)是通过@Transactional注解标识的,并且所有的事务属性也都来自@Transactional注解。
public interface TransactionAttributeSource {
/**
* 确定给定的类是否是这个TransactionAttributeSource元数据格式中的事务属性的候选类。
* * 如果此方法返回false,则不会遍历给定类上的方法,以进行getTransactionAttribute内省。
* * 因此,返回false是对不受影响的类的优化,而返回true仅仅意味着类需要对给定类上的每个方法进
* 行完全自省
* @param targetClass
* @return
*/
default boolean isCandidateClass(Class<?> targetClass) {
return true;
}
//返回给定方法的事务属性,如果该方法是非事务性的,则返回null
@Nullable
TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass);
}
getTransactionAttribute方法用来获取指定方法上的事务属性信息TransactionAttribute继承了TransactionDefinition接口,TransactionDefinition用来配置事务属性信息的源码如下,而TransactionAttribute中新定义了2个方法,一个方法用来指定事务管理器bean名称的,一个用来判断给定的异常是否需要回滚事务
public interface TransactionAttribute extends TransactionDefinition {
/**
* 事务管理器的bean名称
*/
@Nullable
String getQualifier();
/**
* Return labels associated with this transaction attribute.
* <p>This may be used for applying specific transactional behavior
* or follow a purely descriptive nature.
* @since 5.3
*/
Collection<String> getLabels();
/**
* 判断指定的异常是否需要回滚事务
*/
boolean rollbackOn(Throwable ex);
}
TransactionAttributeSource接口有个实现类AnnotationTransactionAttributeSource负责将@Transaction解析为TransactionAttribute对象, AnnotationTransactionAttributeSource内部最会委托给SpringTransactionAnnotationParser#parseTransactionAnnotation方法来解析@Transaction注解,进而得到事务属性配置信息:RuleBasedTransactionAttribute,代码如下:
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
String timeoutString = attributes.getString("timeoutString");
Assert.isTrue(!StringUtils.hasText(timeoutString) || rbta.getTimeout() < 0,
"Specify 'timeout' or 'timeoutString', not both");
rbta.setTimeoutString(timeoutString);
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
rbta.setLabels(Arrays.asList(attributes.getStringArray("label")));
//回滚规则
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
c、TransactionInterceptor
刚才我们说了,TransactionInterceptor就是我们找的Advise。
这个类稍微复杂一点,首先根据事务处理相关的逻辑都放在了其父类TransactionAspectSupport中。此外为了适配动态代理的反射调用(两种代理方式),实现了MethodInterceptor接口。
也就是说,反射发起的入口是MethodInterceptor.invoke(),而反射逻辑在TransactionAspectSupport.invokeWithinTransaction()中。
我们可以简单看invokeWithTransaction()方法中的部分代码:
1.1.5 总结
@EnableTransactionManagement注解主要导入的类,以及对应的类的作用
1.1.6 关键的几个类
TransactionDefinition
- DefaultTransactionDefinition:TransactionDefinition接口的默认的一个实现,编程式事务中通常使用这个
- RuleBasedTransactionAttribute:声明式事务中用到的是这个,这个里面对于事务回滚有一些动态匹配的规则
事务管理器(PlatformTransactionManager)
负责:获取事务、提交事务、回滚事务,Spring中用PlatformTransactionManager接口表示事务管理器,接口中有三个方法
package org.springframework.transaction;
import org.springframework.lang.Nullable;
public interface PlatformTransactionManager extends TransactionManager {
//通过事务管理器获取一个事务,返回TransactionStatus:内部包含事务的状态信息
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
//根据事务的状态信息提交事务
void commit(TransactionStatus status) throws TransactionException;
//根据事务的状态信息回滚事务
void rollback(TransactionStatus status) throws TransactionException;
}
PlatformTransactionManager有多个实现类,操作db用的是hibernate或者mybatis,那么用到的事务管理器是不一样的,常见的事务管理器实现有下面几个
二、事务的创建代理对象过程
这个过程和aop的是一样的。
获取切面列表
三、事务执行流程
3.1 CglibAopProxy#intercept()
3.2 CglibMethodInvocation#proceed()
3.3 ReflectiveMethodInvocation#proceed()
3.4 TransactionInterceptor#invoke()
@Override
@Nullable
public Object invoke(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, invocation::proceed);
}
3.5 TransactionAspectSupport#invokeWithinTransaction()
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
//获取我们的事务属源对象
TransactionAttributeSource tas = getTransactionAttributeSource();
//通过事务属性源对象获取到我们的事务属性信息
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
//获取我们配置的事务管理器对象
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
//从tx属性对象中获取出标注了@Transactionl的方法描述符
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
//处理声明式事务
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
//有没有必要创建事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
//调用钩子函数进行回调目标方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
//抛出异常进行回滚处理
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//清空我们的线程变量中transactionInfo的值
cleanupTransactionInfo(txInfo);
}
//提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
//编程式事务
else {
// 这里不是我们的重点,省略...
}
}
1、getTransactionAttributeSource()
获取事物属性源对象
/**
* Return the transaction attribute source.
*/
@Nullable
public TransactionAttributeSource getTransactionAttributeSource() {
return this.transactionAttributeSource;
}
2、getTransactionAttribute()
/**
* 先进行缓存的获取,如果没有缓存就进行事务属性的获取,如果获取到就放入缓存并返回,否则就返回null
*/
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 判断method所在的class是不是Object类型
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
// 构建缓存key
Object cacheKey = getCacheKey(method, targetClass);
// 从缓存中获取
TransactionAttribute cached = this.attributeCache.get(cacheKey);
// 有缓存,不会每次computeTransactionAttribute
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
// 判断缓存中的对象是不是空事务属性的对象
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
// 存在就直接返回事务属性
return cached;
}
}
else {
// We need to work it out.
// 查找我们的事务注解
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
// 若解析出来的事务注解属性为空
if (txAttr == null) {
// 往缓存中存放空事务注解属性
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
// 我们执行方法的描述符:包名+类名+方法名
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
// 把方法描述设置到事务属性上去
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
// 加入缓存
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
3、determineTransactionManager(txAttr)
获取配置的事务管理器对象
事务管理器的查找顺序:
1、先看@Transactional中是否通过value或者transactionManager指定了事务管理器
2、TransactionInterceptor.transactionManagerBeanName是否有值,如果有,将通过这个查找事务管理器
3、如果上面2种都没有,将从spring容器中查找TransactionManager类型的事务管理器
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
//事务属性不为空
if (txAttr == null || this.beanFactory == null) {
return getTransactionManager();
}
//1,查找我们指定的事务管理器名称
String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
//如果有就返回
return determineQualifiedTransactionManager(this.beanFactory, qualifier);
}
else if (StringUtils.hasText(this.transactionManagerBeanName)) {
//2,如果我们没有指定事务名称,就以transactionManagerBeanName名称做查找
return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
}
else {
//3,如果上述还是没有找,就获取默认的事务管理器
TransactionManager defaultTransactionManager = getTransactionManager();
if (defaultTransactionManager == null) {
//4,如果是空,则在缓存中找,找到就返回
defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
if (defaultTransactionManager == null) {
//5,如果还是没有找到,那就在spring容器中,按类型去查找,然后丢到缓存中去
defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
this.transactionManagerCache.putIfAbsent(
DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
return defaultTransactionManager;
}
}
4、asPlatformTransactionManager()
事务管理器转换成PlatformTransactionManager
private PlatformTransactionManager asPlatformTransactionManager(@Nullable Object transactionManager) {
if (transactionManager == null || transactionManager instanceof PlatformTransactionManager) {
return (PlatformTransactionManager) transactionManager;
}
else {
throw new IllegalStateException(
"Specified transaction manager is not a PlatformTransactionManager: " + transactionManager);
}
}
5、createTransactionIfNecessary()
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
// 如果没有名称指定则使用方法唯一标识,并使用DelegatingTransactionAttribute封装txAttr
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// 获取TransactionStatus事务状态信息
status = tm.getTransaction(txAttr);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
}
}
}
// 根据指定的属性与status准备一个TransactionInfo,
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
5.1 AbstractPlatformTransactionManager#getTransaction()
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// Use defaults if no transaction definition given.
// 如果没有事务定义信息则使用默认的事务管理器定义信息
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 获取事务
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
// 判断当前线程是否存在事务,判断依据为当前线程记录的连接不为空且连接中的transactionActive属性不为空
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
// 当前线程已经存在事务
return handleExistingTransaction(def, transaction, debugEnabled);
}
// Check definition settings for new transaction.
// 事务超时设置验证
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// No existing transaction found -> check propagation behavior to find out how to proceed.
// 如果当前线程不存在事务,但是PropagationBehavior却被声明为PROPAGATION_MANDATORY抛出异常
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
// PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED都需要新建事务
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
//没有当前事务的话,REQUIRED,REQUIRES_NEW,NESTED挂起的是空事务,然后创建一个新事务
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
// 恢复挂起的事务
resume(null, suspendedResources);
throw ex;
}
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
// 创建一个空的事务
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
}
1 DataSourceTransactionManager#doGetTransaction()
protected Object doGetTransaction() {
// 创建一个数据源事务对象
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
// 是否允许当前事务设置保持点
txObject.setSavepointAllowed(isNestedTransactionAllowed());
/**
* TransactionSynchronizationManager 事务同步管理器对象(该类中都是局部线程变量)
* 用来保存当前事务的信息,我们第一次从这里去线程变量中获取 事务连接持有器对象 通过数据源为key去获取
* 由于第一次进来开始事务 我们的事务同步管理器中没有被存放.所以此时获取出来的conHolder为null
*/
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
// 非新创建连接则写false
txObject.setConnectionHolder(conHolder, false);
// 返回事务对象
return txObject;
}
2 AbstractPlatformTransactionManager#suspend()
3 AbstractPlatformTransactionManager#startTransaction()
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
// 是否需要新同步
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 创建新的事务
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 开启事务和连接
doBegin(transaction, definition);
// 新同步事务的设置,针对于当前线程的设置
prepareSynchronization(status, definition);
return status;
}
AbstractPlatformTransactionManager
1 newTransactionStatus()
/**
* 通过给定的参数创建事务状态,有一个非常关键的参数是newTransaction,用于判断是否是新连接,如果事务不存在,那么肯定是true,如果存在,就需要根据传播特性来决定是否是false了
* Create a TransactionStatus instance for the given arguments.
*/
protected DefaultTransactionStatus newTransactionStatus(
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
// 是否需要新同步,只要有新同步且当前无同步激活事务
boolean actualNewSynchronization = newSynchronization &&
!TransactionSynchronizationManager.isSynchronizationActive();
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
}
2 doBegin()
开启事务的关键方法
protected void doBegin(Object transaction, TransactionDefinition definition) {
// 强制转化事务对象
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
// 判断事务对象没有数据库连接持有器
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
// 通过数据源获取一个数据库连接对象
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
// 把我们的数据库连接包装成一个ConnectionHolder对象 然后设置到我们的txObject对象中去
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
// 标记当前的连接是一个同步事务
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
// 为当前的事务设置隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
// 设置先前隔离级别
txObject.setPreviousIsolationLevel(previousIsolationLevel);
// 设置是否只读
txObject.setReadOnly(definition.isReadOnly());
// 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);
}
// 判断事务是否需要设置为只读事务
prepareTransactionalConnection(con, definition);
// 标记激活事务
txObject.getConnectionHolder().setTransactionActive(true);
// 设置事务超时时间
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// Bind the connection holder to the thread.
// 绑定我们的数据源和连接到我们的同步管理器上,把数据源作为key,数据库连接作为value 设置到线程变量中
if (txObject.isNewConnectionHolder()) {
// 将当前获取到的连接绑定到当前线程
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
}
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
// 释放数据库连接
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
3 prepareSynchronization()
/**
* 设置各种线程私有变量的状态
*
* Initialize transaction synchronization as appropriate.
*/
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
if (status.isNewSynchronization()) {
// 绑定事务激活
TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
// 当前事务的隔离级别
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
definition.getIsolationLevel() : null);
// 是否为只读事务
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
// 事务的名称
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
TransactionSynchronizationManager.initSynchronization();
}
}
5.2 prepareTransactionInfo()
/**
* 创建一个TransactionInfo,然后把事务管理器,事务注解属性,方法标识符,事务状态设置进入,然后绑定到当前线程私有变量里
*/
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, String joinpointIdentification,
@Nullable TransactionStatus status) {
// 创建事务信息
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
// We need a transaction for this method...
if (logger.isTraceEnabled()) {
logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
// The transaction manager will flag an error if an incompatible tx already exists.
// 设置新事务状态
txInfo.newTransactionStatus(status);
}
else {
// The TransactionInfo.hasTransaction() method will return false. We created it only
// to preserve the integrity of the ThreadLocal stack maintained in this class.
if (logger.isTraceEnabled()) {
logger.trace("No need to create transaction for [" + joinpointIdentification +
"]: This method is not transactional.");
}
}
// We always bind the TransactionInfo to the thread, even if we didn't create
// a new transaction here. This guarantees that the TransactionInfo stack
// will be managed correctly even if no transaction was created by this aspect.
// 事务信息绑定到当前线程
txInfo.bindToThread();
return txInfo;
}
6、调用proceedWithInvocation()执行业务逻辑
7、completeTransactionAfterThrowing()异常会进入当前方法
/**
* 如果支持回滚的话就进行回滚,否则就处理提交,提交里面如果TransactionStatus.isRollbackOnly()=true的话也会进行回滚处理
*/
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
"] after exception: " + ex);
}
//判断事务是否需要回滚
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
// 利用事务管理器进行回滚
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
}
else {
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
try {
//通过事务管理器提交事务
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by commit exception", ex);
throw ex2;
}
}
}
}
7.1 rollbackOn() 判断当前事务是否需要回滚
@Override
public boolean rollbackOn(Throwable ex) {
RollbackRuleAttribute winner = null;
int deepest = Integer.MAX_VALUE;
//@Transactional中可以通过rollbackFor指定需要回滚的异常列表,通过noRollbackFor属性指定不 需要回滚的异常
//根据@Transactional中指定的回滚规则判断ex类型的异常是否需要回滚
if (this.rollbackRules != null) {
for (RollbackRuleAttribute rule : this.rollbackRules) {
// 如果抛出的异常类型,和事务定义的异常类型匹配,证明该异常需要捕获。
// 之所以用递归,不仅需要判断抛出异常的本身,还需要判断它继承的父类异常,满足任意一个即可捕获。
int depth = rule.getDepth(ex);
if (depth >= 0 && depth < deepest) {
deepest = depth;
winner = rule;
}
}
}
// 若@Transactional注解中没有匹配到,这走默认的规则,将通过super.rollbackOn来判断
if (winner == null) {
return super.rollbackOn(ex);
}
return !(winner instanceof NoRollbackRuleAttribute);
}
super.rollbackOn(ex)源码如下,可以看出默认情况下,异常类型是RuntimeException或者Error的情况下,事务才会回滚。
@Override
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
8、cleanupTransactionInfo()
/**
* 清除事务信息
*
* Reset the TransactionInfo ThreadLocal.
* <p>Call this in all cases: exception or normal return!
* @param txInfo information about the current transaction (may be {@code null})
*/
protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
if (txInfo != null) {
txInfo.restoreThreadLocalStatus();
}
}
9、commitTransactionAfterReturning()
/**
* 调用事务管理器的提交方法
*
* Execute after successful completion of call, but not after an exception was handled.
* Do nothing if we didn't create a transaction.
* @param txInfo information about the current transaction
*/
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
四、总结
1、创建事务流程图
文章来源:https://www.toymoban.com/news/detail-727680.html
2、创建事务流程图
文章来源地址https://www.toymoban.com/news/detail-727680.html
到了这里,关于Spring源码分析(五) 事务全流程分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!