Spring源码分析(五) 事务全流程分析

这篇具有很好参考价值的文章主要介绍了Spring源码分析(五) 事务全流程分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

一、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是一样的。
Spring源码分析(五) 事务全流程分析,spring

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()方法中的部分代码:

Spring源码分析(五) 事务全流程分析,spring

1.1.5 总结

@EnableTransactionManagement注解主要导入的类,以及对应的类的作用

Spring源码分析(五) 事务全流程分析,spring

1.1.6 关键的几个类

TransactionDefinition
  1. DefaultTransactionDefinition:TransactionDefinition接口的默认的一个实现,编程式事务中通常使用这个
  2. RuleBasedTransactionAttribute:声明式事务中用到的是这个,这个里面对于事务回滚有一些动态匹配的规则

Spring源码分析(五) 事务全流程分析,spring

事务管理器(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,那么用到的事务管理器是不一样的,常见的事务管理器实现有下面几个
Spring源码分析(五) 事务全流程分析,spring

二、事务的创建代理对象过程

这个过程和aop的是一样的。
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
获取切面列表
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring

三、事务执行流程

Spring源码分析(五) 事务全流程分析,spring

Spring源码分析(五) 事务全流程分析,spring

3.1 CglibAopProxy#intercept()

Spring源码分析(五) 事务全流程分析,spring

3.2 CglibMethodInvocation#proceed()

Spring源码分析(五) 事务全流程分析,spring

3.3 ReflectiveMethodInvocation#proceed()

Spring源码分析(五) 事务全流程分析,spring

3.4 TransactionInterceptor#invoke()

Spring源码分析(五) 事务全流程分析,spring

@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()

Spring源码分析(五) 事务全流程分析,spring

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()

Spring源码分析(五) 事务全流程分析,spring

	/**
	 * 先进行缓存的获取,如果没有缓存就进行事务属性的获取,如果获取到就放入缓存并返回,否则就返回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类型的事务管理器

Spring源码分析(五) 事务全流程分析,spring

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
Spring源码分析(五) 事务全流程分析,spring

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()

Spring源码分析(五) 事务全流程分析,spring

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()执行业务逻辑

Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring
Spring源码分析(五) 事务全流程分析,spring

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、创建事务流程图

Spring源码分析(五) 事务全流程分析,spring

2、创建事务流程图

Spring源码分析(五) 事务全流程分析,spring文章来源地址https://www.toymoban.com/news/detail-727680.html

到了这里,关于Spring源码分析(五) 事务全流程分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • spring-transaction源码分析(5)TransactionInterceptor事务拦截逻辑

    spring-tx的事务拦截逻辑在TransactionInterceptor类,本文将详细分析其实现方式。 spring-tx的事务拦截逻辑在TransactionInterceptor类,它实现了MethodInterceptor接口。 MethodInterceptor接口的实现类封装aop切面拦截逻辑: TransactionInterceptor类封装了事务拦截逻辑: 事务逻辑在父类TransactionAspec

    2024年02月06日
    浏览(37)
  • 【Spring源码】Spring事务原理

    目录 1、什么是事务 2、Spring事务基本概念 2.1、基础配置 2.1.1、Spring事务的基础配置 2.1.2、Spring事务的传播特性 2.1.3、Spring事务的隔离级别 2.2、基本原理 3、事务嵌套 3.1、PROPAGATION_REQUIRED 3.2、PROPAGATION_REQUIRES_NEW 3.3、PROPAGATION_SUPPORTS 3.4、PROPAGATION_NESTED 4、源码看事务 5、事务失

    2023年04月08日
    浏览(32)
  • 【Spring】Spring之事务底层源码解析

    能使用spring事务解决开发需求 了解spring事务是如何被spring管理的 了解spring事务底层原理实现,比如代理、事务传播机制等 配置数据源及事务管理器: 业务逻辑代码: 调用: 结果: 如上,就是Spring中事务的简单应用,接下来分析Spring事务的实现原理。 开启Spring事务本质上

    2024年02月14日
    浏览(37)
  • Spring Boot原理分析(四):声明式事务

    Spring 提供了多种管理事务的方式,包括编程式事务管理和声明式事务管理两种方式。下面分别介绍这两种方式及其实现方式: 编程式事务管理是通过编写代码来手动管理事务。它需要在事务的开始和结束时,通过编程方式来控制事务的提交和回滚。Spring 提供了 PlatformTransa

    2024年02月17日
    浏览(46)
  • 揭秘Spring事务失效场景分析与解决方案

    在Spring框架中,事务管理是一个核心功能,然而有时候会遇到事务失效的情况,这可能导致数据一致性问题。本文将深入探讨一些Spring事务失效的常见场景,并提供详细的例子以及解决方案。 场景: 当一个事务方法内部调用另一个方法,而被调用的方法没有声明为 @Transact

    2024年02月02日
    浏览(43)
  • spring工程的启动流程?bean的生命周期?提供哪些扩展点?管理事务?解决循环依赖问题的?事务传播行为有哪些?

    Spring工程的启动流程主要包括以下几个步骤: 加载配置文件:Spring会读取配置文件(如XML配置文件或注解配置)来获取应用程序的配置信息。 实例化并初始化IoC容器:Spring会创建并初始化IoC容器,即ApplicationContext。在这一步,Spring会解析配置文件,并将配置的Bean实例化。

    2024年02月12日
    浏览(36)
  • Spring/SpringBoot中的声明式事务和编程式事务源码、区别、优缺点、适用场景、实战

    在现代软件开发中,事务处理是必不可少的一部分。当多个操作需要作为一个整体来执行时, 事务 可以确保 数据的完整性和一致性 ,并避免出现异常和错误情况。在 SpringBoot 框架中,我们可以使用 声明式事务和编程式事务 来管理事务处理。其中事务的坑也是不少,比较常

    2024年02月06日
    浏览(59)
  • 【框架源码】Spring源码解析之Bean创建源码流程

    问题:Spring中是如何初始化单例bean的? 我们都知道Spring解析xml文件描述成BeanDefinition,解析BeanDefinition最后创建Bean将Bean放入单例池中,那么Spring在创建Bean的这个过程都做了什么。 Spring核心方法refresh()中最最重要的一个方法 finishBeanFactoryInitialization() 方法,该方法负责初始化

    2024年02月09日
    浏览(39)
  • spring5源码篇(12)——spring-mvc请求流程

    spring-framework 版本:v5.3.19 总体流程在 DispatchServelt#doDispatch 方法 首先会获取根据url去映射对应的处理器(即接口执行方法) 看到对应的 getHandler 方法 为方便阅读,进入debug。可以看到springmvc默认为我们注册了三个handlerMapping。 springMvc中的各个组件如处理器映射器,处理器适配

    2024年02月15日
    浏览(41)
  • 【框架源码】Spring源码解析之Bean生命周期流程

    观看本文前,我们先思考一个问题,什么是Spring的bean的生命周期?这也是我们在面试的时候,面试官常问的一个问题。 在没有Spring之前,我们创建对象的时候,采用new的方式,当对象不在被使用的时候,由Java的垃圾回收机制回收。 而 Spring 中的对象是 bean,bean 和普通的 J

    2024年02月09日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包