Spring事务源码详解

WSL2不能上网,Failed to connect to github.com port 443问题解决方案 WSL2不能上网: 问题:ping外网无效 例如:ping www.baidu.com失败 解决方案: 在wsl: $sudo vi /etc/wsl.conf wsl.conf: [network] generateResolvConf = false 在PowerShell: $sudo vi /etc/etc/resolv.conf resolv.conf: # This file was automatically generated by WSL. To stop automatic gen 阅读详情

Spring事务三大接口介绍

  • PlatformTransactionManager: (平台)事务管理器
  • TransactionDefinition:事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则
  • TransactionStatus: 事务运行状态

PlatformTransactionManager接口介绍

Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持 久化机制所提供的相关平台框架的事务来实现。 Spring事务管理器的接口是:org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现 就是各个平台自己的事情了。

package org.springframework.transaction;

import org.springframework.lang.Nullable;


public interface PlatformTransactionManager extends TransactionManager {

	/** 
	*	获取事物状态 
	*/
	TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException;

	/** 
	*	事物提交 
	*/
	void commit(TransactionStatus status) throws TransactionException;

	/** 
	*	事物回滚 
	*/
	void rollback(TransactionStatus status) throws TransactionException;

}

TransactionDefinition 事物属性的定义

TransactionDefinition接口中定义了5个方法以及一些表示事务属性的常量比如隔离级别、传播行为等的常量。 我下面只是列出了TransactionDefinition接口中的方法而没有给出接口中定义的常量,该接口中的常量 信息会在后面依次介绍到

package org.springframework.transaction;

import org.springframework.lang.Nullable;


public interface TransactionDefinition {

	/**
	 * 支持当前事物,若当前没有事物就创建一个事物
	 */
	int PROPAGATION_REQUIRED = 0;

	/**
	 * 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
	 */
	int PROPAGATION_SUPPORTS = 1;

	/**
	 * 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
	 */
	int PROPAGATION_MANDATORY = 2;

	/**
	 * 创建一个新的事务,如果当前存在事务,则把当前事务挂起
	 */
	int PROPAGATION_REQUIRES_NEW = 3;

	/**
	 * 以非事务方式运行,如果当前存在事务,则把当前事务挂起
	 */
	int PROPAGATION_NOT_SUPPORTED = 4;

	/**
	 *  以非事务方式运行,如果当前存在事务,则抛出异常。
	 */
	int PROPAGATION_NEVER = 5;

	/**
	 * 表示如果当前正有一个事务在运行中,则该方法应该运行在 一个嵌套的事务中, 
	 * 被嵌套的事务可以独立于封装事务进行提交或者回滚(保存点),
	 * 如果封装事务不存在,行为就像 PROPAGATION_REQUIRES NEW
	 */
	int PROPAGATION_NESTED = 6;


	/**
	 * 使用后端数据库默认的隔离级别,
	 * Mysql 默认采用的 REPEATABLE_READ隔离级别 
	 * Oracle 默认采用的 READ_COMMITTED隔离级别
	 */
	int ISOLATION_DEFAULT = -1;

	/**
	 * 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
	 */
	int ISOLATION_READ_UNCOMMITTED = 1;  
	// same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;

	/**
	 * 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
	 */
	int ISOLATION_READ_COMMITTED = 2;  
	// same as java.sql.Connection.TRANSACTION_READ_COMMITTED;

	/**
	 * 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,
	 * 可以阻止脏读和不可重复读,但幻读仍有可能发生
	 */
	int ISOLATION_REPEATABLE_READ = 4;  
	// same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;

	/**
	 * 最高的隔离级别,完全服从ACID的隔离级别。
	 * 所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰, 
	 * 也就是说,该级别可以防止脏读、不可重复读以及幻读。
	 * 但是这将严重影响程序的性能通常情况下也不会用到该级别
	 */
	int ISOLATION_SERIALIZABLE = 8;  
	// same as java.sql.Connection.TRANSACTION_SERIALIZABLE;


	/**
	 * 使用默认的超时时间
	 */
	int TIMEOUT_DEFAULT = -1;


	/**
	 * 获取事物的传播行为
	 */
	default int getPropagationBehavior() {
		return PROPAGATION_REQUIRED;
	}

	/**
	 * 获取事物的隔离级别
	 */
	default int getIsolationLevel() {
		return ISOLATION_DEFAULT;
	}

	/**
	 * 返回事物的超时时间
	 */
	default int getTimeout() {
		return TIMEOUT_DEFAULT;
	}

	/**
	 * 返回当前是否为只读事物
	 */
	default boolean isReadOnly() {
		return false;
	}

	/**
	 * 获取事物的名称
	 */
	@Nullable
	default String getName() {
		return null;
	}

}

在这里插入图片描述

TransactionStatus接口介绍

TransactionStatus接口用来记录事务的状态 该接口定义了一组方法,用来获取或判断事务的相应状态信 息.
PlatformTransactionManager.getTransaction(…) 方法返回一个 TransactionStatus 对象。返回的 TransactionStatus 对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的 事物

package org.springframework.transaction;

import java.io.Flushable;


public interface TransactionStatus extends SavepointManager, Flushable {

	/**
	 * 是否为新事物
	 */
	boolean isNewTransaction();

	/**
	 * 是否有保存点
	 */
	boolean hasSavepoint();

	/**
	 * 设置为只回滚
	 */
	void setRollbackOnly();

	/**
	 * 是否为只回滚
	 */
	boolean isRollbackOnly();

	/**
	 * 属性
	 */
	@Override
	void flush();

	/**
	 * 判断当前事物是否已经完成
	 */
	boolean isCompleted();

}

我们来分析@EnableTransactionManagement注解来给我们容器加入了什么组件

在这里插入图片描述

从源码开始分析注册的组件

EnableTransactionManagement源码分析
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

	/**
	 * 指定使用什么代理模式(true为cglib代理,false 为jdk代理)
	 */
	boolean proxyTargetClass() default false;

	/**
	 * 通知模式 是使用代理模式还是aspectj 我们一般使用Proxy
	 */
	AdviceMode mode() default AdviceMode.PROXY;

	/**
	 * Indicate the ordering of the execution of the transaction advisor
	 * when multiple advices are applied at a specific joinpoint.
	 * <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.
	 */
	int order() default Ordered.LOWEST_PRECEDENCE;

}

我们从上面处的源码可以分析处他通过@Import导入了 TransactionManagementConfigurationSelector组件

TransactionManagementConfigurationSelector源码分析
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	/**
	 * 往容器中添加组件 
	 * 1) AutoProxyRegistrar
	 * 2) ProxyTransactionManagementConfiguration
	 */
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		//因为我们配置的默认模式是PROXY
		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);
	}

}

首先我们来分析AutoProxyRegistrar给我们容器中干了什么?

从源码分析出,AutoProxyRegistrar为我们容器注册了一个InfrastructureAdvisorAutoProxyCreator组件
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	private final Log logger = LogFactory.getLog(getClass());

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		boolean candidateFound = false;
		//从我们传入进去的配置类上获取所有的注解的
		Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
		//循环我们上一步获取的注解
		for (String annoType : annoTypes) {
			//获取注解的元信息
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
			if (candidate == null) {
				continue;
			}
			//获取注解的mode属性
			Object mode = candidate.get("mode");
			//获取注解的proxyTargetClass
			Object proxyTargetClass = candidate.get("proxyTargetClass");
			//根据mode和proxyTargetClass的判断来注册不同的组件
			if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
					Boolean.class == proxyTargetClass.getClass()) {
				candidateFound = true;
				if (mode == AdviceMode.PROXY) {
					//重点进入到这一步
					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));
		}
	}

}

在这里我们可以看到,registerBeanDefinitions 方法中解析了 事务注解,并注册了自动代理创建器。这里自动代理创建器我们在Aop 源码中提到过,是Aop 创建的核心。

AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)这一步最主要的作用将自动代理创建器 InfrastructureAdvisorAutoProxyCreator 注册到了 Spring容器中。

public abstract class AopConfigUtils {
	/**
	*	...略
	*/
		@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAutoProxyCreatorIfNecessary(registry, null);
	}

	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}

		@Nullable
	private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		//判断容器中有没有org.springframework.aop.config.internalAutoProxyCreator
		//名字的bean定义
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}
		//自己注册一个org.springframework.aop.config.internalAutoProxyCreator的组件
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}
	/**
	*	...略
	*/

}

到这里我们基本可以断定和 Aop 的逻辑基本相同了,只不过事务默认自动注入的自动代理创建器是 InfrastructureAdvisorAutoProxyCreator 类型。

注意:

  1. 在上篇Aop 中我们知道 Aop创建的自动代理创建器类型是 AnnotationAwareAspectJAutoProxyCreator,而事务创建的类型是 InfrastructureAdvisorAutoProxyCreator。
  2. 这里之所以 beanName (AUTO_PROXY_CREATOR_BEAN_NAME) 和 bean的类型并不相同,是因为这个beanName 特指内部的自动代理创建器,但是自动创建代理器会对应多种不同的实现方式。比如在默认的事务中,注入的bean类型却为InfrastructureAdvisorAutoProxyCreator,而AOP的实现却是 AnnotationAwareAspectJAutoProxyCreator。
  3. 关于自动代理创建器优先级的问题,我们可以看到APC_PRIORITY_LIST集合的顺序,下标越大,优先级越高。因此可以得知优先级的顺序应该是
    InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator
InfrastructureAdvisorAutoProxyCreator

我们看看InfrastructureAdvisorAutoProxyCreator的继承关系
在这里插入图片描述
这个类的继承关系是比较复杂的,我们只挑选我们最关注的来分析吧。

从图上可以看到InfrastructureAdvisorAutoProxyCreator类间接实现了BeanPostProcessor接口,这个接口主要的所用是对每一个bean对象初始化前后做增强。在每一个bean初始化前调用postProcessBeforeInitialization,初始化后调用postProcessAfterInitialization。

然后我们在来分析一下 TransactionManagementConfigurationSelector 为我们还导入了一个类 ProxyTransactionManagementConfiguration
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

	/**
	* 为我我们容器中导入了 
	* beanName为org.springframework.transaction.config.internalTransactionAdvisor 
	* 类型为BeanFactoryTransactionAttributeSourceAdvisor
	* 的增强器
	*/
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource());
		advisor.setAdvice(transactionInterceptor());
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}
	
	/** 
	* 定义了一个事物属性源对象 
	*/
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

	/** 
	* 事物拦截器对象 
	*/
	@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;
	}

}

ProxyTransactionManagementConfiguration 代码如下,并没有逻辑,就是将几个Bean注入的到容器中。不过这几个bean可都是关键bean,所以我们需要对其中的bean进行分析。

  • BeanFactoryTransactionAttributeSourceAdvisor: 事务的增强器,该方法是否开始事务,是否需要代理该类都在该类中判断
  • TransactionAttributeSource: 保存了事务相关的一些信息资源。
  • TransactionInterceptor: 事务拦截器,事务生成代理类时使用的代理拦截器,编写了事务的规则
@SuppressWarnings("serial")
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
	private TransactionAttributeSource transactionAttributeSource;

	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};


	/**
	 * Set the transaction attribute source which is used to find transaction
	 * attributes. This should usually be identical to the source reference
	 * set on the transaction interceptor itself.
	 * @see TransactionInterceptor#setTransactionAttributeSource
	 */
	public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
		this.transactionAttributeSource = transactionAttributeSource;
	}

	/**
	 * Set the {@link ClassFilter} to use for this pointcut.
	 * Default is {@link ClassFilter#TRUE}.
	 */
	public void setClassFilter(ClassFilter classFilter) {
		this.pointcut.setClassFilter(classFilter);
	}

	@Override
	public Pointcut getPointcut() {
		return this.pointcut;
	}

}

这个根据上面的分析,我们可以知道这个是事务判断的核心,BeanFactoryTransactionAttributeSourceAdvisor是Advisor子类,那么我们可以知道其中有两个关键属性: Pointcut(判断是否可以作用于当前方法)和 Advice(作用于当前方法的具体逻辑)。

通过 Aop文章的分析我们可以知道,Advisor 判断一个方法是否匹配,是通过其 Pointcut.matchs 属性来判断的。然后我们通过上面的代码,发现其 Pointcut 的实现类是 TransactionAttributeSourcePointcut,也就是说,一个方法是否需要使用事务,是通过 TransactionAttributeSourcePointcut#matches 方法判断的。

TransactionAttributeSourcePointcut
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

	@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);
	}

	@Override
	public boolean equals(Object other) {
		if (this == other) {
			return true;
		}
		if (!(other instanceof TransactionAttributeSourcePointcut)) {
			return false;
		}
		TransactionAttributeSourcePointcut otherPc = (TransactionAttributeSourcePointcut) other;
		return ObjectUtils.nullSafeEquals(getTransactionAttributeSource(), otherPc.getTransactionAttributeSource());
	}

	@Override
	public int hashCode() {
		return TransactionAttributeSourcePointcut.class.hashCode();
	}

	@Override
	public String toString() {
		return getClass().getName() + ": " + getTransactionAttributeSource();
	}


	/**
	 * Obtain the underlying TransactionAttributeSource (may be {@code null}).
	 * To be implemented by subclasses.
	 */
	@Nullable
	protected abstract TransactionAttributeSource getTransactionAttributeSource();

}
AnnotationTransactionAttributeSource
@SuppressWarnings("serial")
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
		implements Serializable {
		
	// JTA 1.2事务注解是否被使用
	private static final boolean jta12Present;

	// EJB 3 事务注解是否被使用
	private static final boolean ejb3Present;

	static {
		ClassLoader classLoader = AnnotationTransactionAttributeSource.class.getClassLoader();
		// 根据注解类的存在性判断 JTA 1.2 事务注解是否被使用
		jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader);
		// 根据注解类的存在性判断 EJB 3 事务注解是否被使用
		ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader);
	}

	// 指出仅仅处理public方法(基于代理的AOP情况下的典型做法),
	// 还是也处理protected/private方法(使用AspectJ类织入方式下的典型做法)
	private final boolean publicMethodsOnly;

	// 保存用于分析事务注解的事务注解分析器
	private final Set<TransactionAnnotationParser> annotationParsers;


	/**
	 * 构造函数, publicMethodsOnly 缺省使用 true
	 */
	public AnnotationTransactionAttributeSource() {
		this(true);
	}

	/**
	 * 构造函数
	 */
	public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
		this.publicMethodsOnly = publicMethodsOnly;
		// 下面这段逻辑主要是准备用于分析事务注解的各个分析器,放到属性 annotationParsers 中
		// Spring事务注解分析器总是
		// 会被使用 : SpringTransactionAnnotationParser
		if (jta12Present || ejb3Present) {
			// 根据 JTA , EJB 事务注解类的存在性决定要不要添加相应的事务注解处理器
			// JTA 事务注解分析器 : JtaTransactionAnnotationParser
			// EJB 事务注解分析器 : Ejb3TransactionAnnotationParser
			this.annotationParsers = new LinkedHashSet<>(4);
			this.annotationParsers.add(new SpringTransactionAnnotationParser());
			if (jta12Present) {
				this.annotationParsers.add(new JtaTransactionAnnotationParser());
			}
			if (ejb3Present) {
				this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
			}
		}
		else {
			this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
		}
	}

	/**
	 * 创建一个定制的 AnnotationTransactionAttributeSource ,使用给定的事务注解分析器(一个),
	 * publicMethodsOnly 缺省使用 true,仅针对public方法工作
	 */
	public AnnotationTransactionAttributeSource(TransactionAnnotationParser annotationParser) {
		this.publicMethodsOnly = true;
		Assert.notNull(annotationParser, "TransactionAnnotationParser must not be null");
		this.annotationParsers = Collections.singleton(annotationParser);
	}

	/**
	 * 创建一个定制的 AnnotationTransactionAttributeSource ,使用给定的事务注解分析器(多个),
	 * publicMethodsOnly 缺省使用 true,仅针对public方法工作
	 */
	public AnnotationTransactionAttributeSource(TransactionAnnotationParser... annotationParsers) {
		this.publicMethodsOnly = true;
		Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
		this.annotationParsers = new LinkedHashSet<>(Arrays.asList(annotationParsers));
	}

	/**
	 * 创建一个定制的 AnnotationTransactionAttributeSource ,使用给定的事务注解分析器(多个),
	 * publicMethodsOnly 缺省使用 true,仅针对public方法工作
	 */
	public AnnotationTransactionAttributeSource(Set<TransactionAnnotationParser> annotationParsers) {
		this.publicMethodsOnly = true;
		Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
		this.annotationParsers = annotationParsers;
	}

	// 获取某个类上的事务注解属性
	@Override
	@Nullable
	protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
		return determineTransactionAttribute(clazz);
	}

	// 获取某个方法上的事务注解属性
	@Override
	@Nullable
	protected TransactionAttribute findTransactionAttribute(Method method) {
		return determineTransactionAttribute(method);
	}

	/**
	 * 分析获取某个被注解的元素,具体的来讲,指的是一个类或者一个方法上的事务注解属性。
	 * 该实现会遍历自己属性annotationParsers中所包含的事务注解属性分析器试图获取事务注解属性,
	 * 一旦获取到事务注解属性则返回,如果获取不到则返回null,表明目标类/方法上没有事务注解。
	 */
	@Nullable
	protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
		for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
			TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
			if (attr != null) {
				return attr;
			}
		}
		return null;
	}

	/**
	 * 缺省情况下,仅仅public方法上的事务注解才被识别和应用
	 */
	@Override
	protected boolean allowPublicMethodsOnly() {
		return this.publicMethodsOnly;
	}


	@Override
	public boolean equals(Object other) {
		if (this == other) {
			return true;
		}
		if (!(other instanceof AnnotationTransactionAttributeSource)) {
			return false;
		}
		AnnotationTransactionAttributeSource otherTas = (AnnotationTransactionAttributeSource) other;
		return (this.annotationParsers.equals(otherTas.annotationParsers) &&
				this.publicMethodsOnly == otherTas.publicMethodsOnly);
	}

	@Override
	public int hashCode() {
		return this.annotationParsers.hashCode();
	}

}

  • 从类 AnnotationTransactionAttributeSource的源代码可以看到,它仅仅通过findTransactionAttribute方法实现类如何找到指定类/方法的事务注解属性,但是自身并没有提供public方法供调用者使用。
  • 实际上,类 AnnotationTransactionAttributeSource提供给调用者的服务方法是 getTransactionAttribute,而该方法定义在其父类AbstractFallbackTransactionAttributeSource中。
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {

	/**
	 * 针对没有事务注解属性的方法进行事务注解属性缓存时使用的特殊值,用于标记该方法没有事务注解属性,
	 * 从而不用在首次缓存在信息后,不用再次重复执行真正的分析
	 */
	@SuppressWarnings("serial")
	private static final TransactionAttribute NULL_TRANSACTION_ATTRIBUTE = new DefaultTransactionAttribute() {
		@Override
		public String toString() {
			return "null";
		}
	};


	/**
	 * Logger available to subclasses.
	 * <p>As this base class is not marked Serializable, the logger will be recreated
	 * after serialization - provided that the concrete subclass is Serializable.
	 */
	protected final Log logger = LogFactory.getLog(getClass());

	/**
	 * 方法上的事务注解属性缓存,key使用目标类上的方法,使用类型MethodClassKey来表示
	 */
	private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024);


	/**
	 * 获取指定方法上的注解事务属性
	 * 如果方法上没有注解事务属性,则使用目标方法所属类上的注解事务属性
	 */
	@Override
	@Nullable
	public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		if (method.getDeclaringClass() == Object.class) {
			// 如果目标方法是内置类Object上的方法,总是返回null,这些方法上不应用事务
			return null;
		}

		// 先查看针对该方法是否已经获取过其注解事务属性并且已经缓存
		Object cacheKey = getCacheKey(method, targetClass);
		TransactionAttribute cached = this.attributeCache.get(cacheKey);
		if (cached != null) {
			// 目标方法上的事务注解属性信息已经缓存的情况
			// or an actual transaction attribute.
			if (cached == NULL_TRANSACTION_ATTRIBUTE) {
				// 目标方法上上并没有事务注解属性,但是已经被尝试分析过并且已经被缓存,
				// 使用的值是 NULL_TRANSACTION_ATTRIBUTE,所以这里再次尝试获取其注解事务属性时,
				// 直接返回 null
				return null;
			}
			else {
				// 返回所缓存的注解事务属性
				return cached;
			}
		}
		else {
			// 目标方法上的注解事务属性尚未分析过,现在分析获取之
			TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
			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;
		}
	}

	/**
	 * Determine a cache key for the given method and target class.
	 * <p>Must not produce same key for overloaded methods.
	 * Must produce same key for different instances of the same method.
	 * @param method the method (never {@code null})
	 * @param targetClass the target class (may be {@code null})
	 * @return the cache key (never {@code null})
	 */
	protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
		return new MethodClassKey(method, targetClass);
	}

	/**
	 * 查找目标方法上的事务注解属性,但只是查找和返回,并不做缓存,效果上讲,可以认为
	 * #getTransactionAttribute 是增加了缓存机制的方法#computeTransactionAttribute
	 */
	@Nullable
	protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		// 如果事务注解属性分析仅仅针对public方法,而当前方法不是public,则直接返回null
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}

		// 参数 method 可能是基于接口的方法,该接口和参数targetClass所对应的类不同(也就是说:
		// targetClass是相应接口的某个实现类),而我们这里需要的属性是要来自targetClass的,
		// 所以这里先获取targetClass上的那个和method对应的方法,这里 method, specificMethod 
		// 都可以认为是潜在的目标方法
		Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

		// 首先尝试检查事务注解属性直接标记在目标方法 specificMethod 上
		TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
		if (txAttr != null) {
			// 事务注解属性直接标记在目标方法上
			return txAttr;
		}

		// 然后尝试检查事务注解属性是否标记在目标方法 specificMethod 所属类上
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
			// 事务注解属性是否标记在目标方法所属类上
			return txAttr;
		}
		
		// 逻辑走到这里说明目标方法specificMethod,也就是实现类上的目标方法上没有标记事务注解属性
		if (specificMethod != method) {
			// 如果 specificMethod 和 method 不同,则说明 specificMethod 是具体实现类
			// 的方法,method 是实现类所实现接口的方法,现在尝试从 method 上获取事务注解属性
			txAttr = findTransactionAttribute(method);
			if (txAttr != null) {
				return txAttr;
			}
			// 现在尝试在 method 所属类上查看是否有事务注解属性
			txAttr = findTransactionAttribute(method.getDeclaringClass());
			if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
				return txAttr;
			}
		}
		// specificMethod 方法/所属类上没有事务注解属性,
		// method 方法/所属类上也没有事务注解属性,
		// 所以返回 null
		return null;
	}


	/**
	 * 从指定类上获取事务注解属性,由子类负责提供实现
	 */
	@Nullable
	protected abstract TransactionAttribute findTransactionAttribute(Class<?> clazz);

	/**
	 * 从指定方法上获取事务注解属性,由子类负责提供实现
	 */
	@Nullable
	protected abstract TransactionAttribute findTransactionAttribute(Method method);

	/**
	 * Should only public methods be allowed to have transactional semantics?
	 * <p>The default implementation returns {@code false}.
	 */
	protected boolean allowPublicMethodsOnly() {
		return false;
	}

}

  • AbstractFallbackTransactionAttributeSource是接口TransactionAttributeSource的抽象实现,也是上面提到的工具类AnnotationTransactionAttributeSource的父类。
  • 方法AbstractFallbackTransactionAttributeSource#getTransactionAttribute是给调用者使用的获取指定方法的事务注解属性的入口

我们的分析到这里,就已经可以知道了Spring 中对事务注解的解析过程,逻辑基本和 Spring Aop 类似。

  1. @EnableTransactionManagement 通过引入 TransactionManagementConfigurationSelector 注册了 AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration 两个类。
  2. AutoProxyRegistrar 中注册了 InfrastructureAdvisorAutoProxyCreator 自动代理创建器
  3. InfrastructureAdvisorAutoProxyCreator 中拦截bean的创建过程,通过 BeanFactoryTransactionAttributeSourceAdvisor 来判断bean中是否有事务注解,有则进行代理。
TransactionInterceptor
@SuppressWarnings("serial")
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

	/**
	*	... 略
	*/


	@Override
	@Nullable
	public Object invoke(MethodInvocation invocation) throws Throwable {
		//获取代理对象的目标class
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		//使用事务调用
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

	/**
	*	... 略
	*/

}

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
	
		@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {

		// 获取事务数据源,这里获取的数据源就是在  TransactionInterceptor 注入的时候的设置的属性transactionAttributeSource = AnnotationTransactionAttributeSource。
		// 在 ProxyTransactionManagementConfiguration 中完成	
		TransactionAttributeSource tas = getTransactionAttributeSource();
		// 1. 获取对应的事务属性
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		// 2. 获取一个合适的 TransactionManager 
		final PlatformTransactionManager tm = determineTransactionManager(txAttr);
		// 构造方法的唯一标识( 全路径了类名.方法)
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
		// 4. 对不同事务情景的处理
		// 声明式事务的处理
		// 如果txAttr为空或者tm 属于非CallbackPreferringPlatformTransactionManager,执行目标增强
		// 在TransactionManager上,CallbackPreferringPlatformTransactionManager实现PlatformTransactionManager接口,暴露出一个方法用于执行事务处理中的回调
		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// 5.如果有必要,创建事务信息。主要由于事务的传播属性,所以这里并不一定会创建事务
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			try {
				// 6. 执行被增强的方法
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// 7. 异常回滚
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				// 8. 提交之前清除事务信息
				cleanupTransactionInfo(txInfo);
			}
			// 9.提交事务
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
		// 编程式事务(CallbackPreferringPlatformTransactionManager)的处理。这里的逻辑基本都被封装了
		else {
			final ThrowableHolder throwableHolder = new ThrowableHolder();

			// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
			try {
				// 直接调用execute 方法。由于事务的提交回滚等操作都已经封装好了,所以这里并没有对事务进行详细的操作。
				Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
					// 准备事务信息
					TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
					try {
						// 执行方法
						return invocation.proceedWithInvocation();
					}
					catch (Throwable ex) {
						if (txAttr.rollbackOn(ex)) {
							// A RuntimeException: will lead to a rollback.
							if (ex instanceof RuntimeException) {
								throw (RuntimeException) ex;
							}
							else {
								throw new ThrowableHolderException(ex);
							}
						}
						else {
							// A normal return value: will lead to a commit.
							throwableHolder.throwable = ex;
							return null;
						}
					}
					finally {
						// 清除事务信息	
						cleanupTransactionInfo(txInfo);
					}
				});

				// Check result state: It might indicate a Throwable to rethrow.
				if (throwableHolder.throwable != null) {
					throw throwableHolder.throwable;
				}
				return result;
			}
			catch (ThrowableHolderException ex) {
				throw ex.getCause();
			}
			catch (TransactionSystemException ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
					ex2.initApplicationException(throwableHolder.throwable);
				}
				throw ex2;
			}
			catch (Throwable ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
				}
				throw ex2;
			}
		}
	}


}

从上面的代码中,我们可以知道Spring支持声明式事务和编程式事务两种处理。两者的实现本质基本相同。在invoke方法中我们也可以看到这两种方式的实现,通常我们使用的都是通过 @Transactional 注解修饰的声明式事务,所以我们下面主要分析 声明式事务 的处理过程。

  1. 获取事务属性 TransactionAttribute,TransactionAttribute 中包含 传播属性,timeout 等事务属性信息。如果是使用 @Transactional 注解,这个解析过程是在AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method) 中完成

  2. 加载配置中的 TrancationManager, 事务管理器,是事务实现的基础,我们这里获取到的是 DataSourceTransactionManager。

  3. 对反应式事务的处理。

  4. 不同事务处理方式使用不同的逻辑。在上面的代码中主要是两种情况,一是声明式事务,这种情况是通过 @Transactional 注解修饰方法来表示开启事务。另一种情况是编程式事务,即可以通过xml方式或者配置类方式来进行完成事务功能,其实TransactionTemplate 的实现就是编程式事务,但通过 TransactionTemplate 并不会走到这个逻辑,这里的编程式事务应该单独是通过xml或者配置类方式来配置的。
    对于声明式事务的处理和编程式事务的处理,区别主要在两点。一是事务属性上,因为编程式事务是不需要事务属性的,二是 TransactionManager 的不同,CallbackPreferringPlatformTransactionManager实现了 PlatformTransactionManager 接口,暴露了一个方法用于执行事务处理中的回调。所以这两种方式都可以作为事务处理方式的判断。

  5. 在目标方法执行前获取事务并收集事务信息。
    事务信息与事务属性并不相同,也就是 TransactionInfo 和 TransactionAttribute 并不相同,TransactionInfo 中包含TransactionAttribute 信息,并且处理 TransactionAttribute 之外还有其他事物信息,比如PlatformTransactionManager 以及 TransactionStatus相关信息。

  6. 执行目标方法

  7. 如果出现异常,则进行回滚。这里需要注意,默认的情况下只有 RuntimeException 异常才会执行回滚。可以通过 @Transactional(rollbackFor = Exception.class) 的方式来指定触发回滚的异常

  8. 提交事务前的事务信息清除

  9. 提交事务

  10. 若是 编程式事务,则直接执行execute方法即可,这里就不再讲解。

Cadence IC618与Spectre231安装配置全攻略:License、环境变量与依赖检查 EDA工具部署中,License管理与环境变量隔离是核心难点。FlexLM作为通用授权机制,通过守护进程和端口配置实现工具授权;环境变量则控制工具路径与库加载顺序,避免版本冲突。合理配置可确保IC618与Spectre231稳定运行,提升仿真效率。典型应用场景包括模拟IC设计、高校实验室及企业级EDA环境。本文聚焦Cadence IC618与Spectre231的安装实践,详解License配置、环境隔离及依赖检查,助你快速搭建可靠设计环境。 阅读详情

相关推荐

LabVIEW数据采集-数字I/O/计数器

labview 数据采集 数字I/O 计数器

weixin_43781045的博客 5617

Spring事务源码原理详解(保姆级)

通过5个案例,50张图文讲解,从Spring事务源码原理带你彻底搞定Spring事务,工作面试一套拿捏

真正的大师,永远怀着一颗学徒的❤ 7658

从零到千兆:KSZ9031 PHY芯片在Zynq PS端的驱动移植心路历程

本文详细记录了在Xilinx Zynq-7000平台(基于XC7Z020芯片)上,为KSZ9031千兆以太网PHY芯片移植LwIP协议栈驱动的完整过程。从硬件连接配置、Vivado工程设置到LwIP库的深度修改与调试,分享了解决PHY识别、自协商及性能优化等关键问题的实战经验,助力开发者实现稳定的千兆网络连接。

honey的博客 1104

spring声明式事务源码详解

是Spring框架中用于声明式事务管理的一个注解,主要通过 AOP(面向切面编程)来实现事务管理。可以被应用于接口定义、接口方法、类定义或类的public方法上。如果方法正常执行完成且没有异常,调用方法。如果执行中出现异常,调用方法。两个方法内部都会判断是否存在事务以及是否满足回滚条件来决定最终执行提交操作还是回滚操作。上述例子1.1中,未添加事务,不受事务控制,因此修改操作生效。上述例子1.2中,因加入事务注解,指定回滚异常类型,在中逻辑判断需要回滚,调用方法执行回滚操作,因此修改操作不生效。

zhuanzhuantech的博客 1547

保姆级教程:中科蓝讯Downloader配置详解,从软硬开关机到EQ调音一步到位

本文详细介绍了中科蓝讯Downloader的配置流程,从硬件初始化到音频调优的全方位指南。涵盖软硬开关机选择、电源管理、DAC校准、EQ调音等关键步骤,帮助开发者高效完成配置并避免常见问题。特别适合需要精确控制音频设备和电源管理的中科蓝讯芯片开发者。

weixin_33670786的博客 308

用Python的fengwo模块复刻通达信筹码峰(COST/WINNER),选股效率提升10倍

本文介绍了如何使用Python的fengwo模块高效复刻通达信的筹码峰(COST/WINNER)计算,显著提升选股效率。通过C++内核与多线程优化,fengwo模块将传统Python实现的数小时计算压缩至分钟级,解决了量化交易中的性能瓶颈问题。文章详细解析了筹码峰计算原理、fengwo模块的技术架构及实战应用,助力量化开发者构建高效选股系统。

weixin_29062823的博客 438

spring事务源码剖析

spring事务解析

qq_31671187的博客 468

在中国大陆使用 LiveKit 集成阿里云语音交互服务

通过集成阿里云的语音和模型服务,我们可以快速构建出适合中国用户的 LiveKit 智能语音应用。LiveKit Agents 框架的模块化设计使得替换底层服务变得异常简单,只需要更换相应的插件实例即可。使用 WebSocket 版本的阿里云 ASR 接口以获得更低的延迟。利用通义千问的 Function Calling 能力对接智能家居或企业内部 API。结合 LiveKit 的视频处理能力,打造具备视觉交互的数字人。希望这篇博客能为你在实时音视频与 AI 结合的探索之路上提供帮助!

星空漫野 1234

【源码系列】Spring事务执行原理源码

其实事务的源码还是比较好理解的,首先要知道它是基于AOP来实现的,明白事务传播特性,搞清楚各个特性的作用,执行流程主要分为三大步 事务准备:通过TransactionManager(事务管理器)、TransactionAttribute(事务注解属性的包装)、TransactionStatus(包含了连接对象、被挂起的事务等)来实例化TransacationInfo对象, 事务执行:事务代码执行,成功提交(如果当前事务不是一个全新的事务那么会做空提交,需要第一个创建事务的才提交)、失败回滚(如果当前事务有

苏雨丶 1918

Verilog——反相器

反相器代码: module inv( A, Y );//A,Y是端口 //定义端口属性 input A; output Y; //定义输入输出关系 assign Y=~A;//Y等于A的反 endmodule //inv是module的名字

weixin_41788560的博客 9499

2020年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第3题)

2020年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第3题)

王老师青少年编程 989

Spring事务源码

阶段核心机制启动导入和Advisor代理创建为带的 Bean 创建代理(JDK/CGLIB)方法调用代理触发事务开启调用线程绑定使用存储连接DAO 访问等从获取当前事务连接自调用失效绕过代理,无法拦截🔁一句话总结:Spring 事务 =AOP 动态代理拦截的状态管理。理解这三者如何协同工作,就真正掌握了 Spring 事务的“内核”。

weixin_43578751的博客 1122

什么是垂直同步?电脑快速消除屏幕撕裂与提升游戏性能的方法 垂直同步、游戏画面撕裂、游戏优化、VSync、FPS、FreeSync、G-Sync、显卡驱动更新、游戏画质、输入延迟

看这张动图,左边的画面出现了明显“切开”的断层现象,而右边画面非常流畅,没有撕裂。这正是「垂直同步」开关的区别。:每秒生成多少帧图像。比如 60FPS 表示一秒钟显示 60 张图片。刷新率(Refresh Rate):显示器每秒刷新几次画面,单位是赫兹(Hz)。60Hz 表示每秒刷新 60 次。参数说明FPS显卡渲染速度(逻辑帧率)刷新率显示器的显示频率(物理限制)当 FPS 高于刷新率时,显卡渲染的画面来不及被显示器显示,导致撕裂。屏幕撕裂(Screen Tearing)

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1343

spring基于注解的事务源码解析,基本包含了spring事务的所有内容

spring事务的源码解析,以及mysql事务的一些相关知识的解析

qq_37133838的博客 1138

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【Spring】深入Spring事务源码-@Transactional实现

本文深入解析了Spring事务管理机制的核心实现原理。首先介绍了@Transactional注解的底层实现基于SpringAOP,并通过@EnableTransactionManagement注解启用事务功能,其通过TransactionManagementConfigurationSelector自动配置了AutoProxyRegistrar和ProxyTransactionManagementConfiguration两个关键组件。 帮助开发者深入理解Spring事务的底层机制。

u014135956的博客 1116

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Spring源码之事务源码解析

文章目录前言类结构体系产生过程创建过程执行过程 前言 猿猿们都知道,IOC和AOP很重要,事务也很重要,这篇就来解析事务的源码。 类结构体系 产生过程 老规矩,先来看一下Spring IOC容器是怎么初始化的,再看它的创建过程,最后看执行过程。 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented ...

从入门到脱发 777

【Spring专题】Spring之事务底层源码解析

@Transactional 注解相信大家并不陌生,平时开发中很常用的一个注解。它可以作用在类上面,所有该类的public方法都配置相同的事务属性信息;也可以作用在方法上面,表示方法被纳入了事务管理钟。被事务管理的方法,能保证方法内多个数据库操作要么同时成功、要么同时失败。但是使用@Transactional注解时又需要注意一些细节,不然一个不小心就事务失效了。 下面注解的源码,我们来看看它都有什么属性: 上面贴的基本上是我们在业务代码中能使用到的关于注解的了。通过属性我们可以看出,注解具备以下作用:看完之

qq_32681589的博客 1488

【源码】Spring事务之传播特性的详解

本篇从源码的角度,详细分享了事务的七种传播特性Propagation,并从源码分析了传播特性的实现原理。

JingAi_jia917的博客 1286

spring源码分析-事务的底层源码-1

其实这属于AOP的知识,也就是springAOP在完成代理的时候会进行切面当中的连接点信息判断是否需要增强;上图所示当调用inventoryService的save方法的时候,假设inventoryService没有实例化,那么spring容器会实例化这个bean,会走他的生命周期,当走到BeanPostProcessor的postProcessAfterInitialization方法的时候会从容器当中拿出所有的后置处理器依次执行他们的postProcessAfterInitialization方法;

java_lyvee的专栏 2412

Spring源码之事务管理

Spring事务管理的核心实现原理为通过AOP的方式,使用事务拦截器 (Transaction Interceptor)对有事务注解标记@Transactional的业务方法进行拦截,进行统一的事务开启、提交/回滚的管理。通过将autocommit设置为false,通过任务执行情况控制执行commit或者rollback。在使用方式上提供了编程式事务、声明式事务来攻程序员灵活选用,以满足不同场景的需求。

qq_26783889的博客 1192

Spring源码分析-事务源码分析

然后我们在上面的中看到了这个对象,通过字面含义是事务定义。我们来看看结构。也就是中定义了事务的传播属性和隔离级别,然后来看看具体的体系结构DefaultTransactionDefinition:是事务定义的默认实现DefaultTransactionAttribute:扩展了TransactionAttribute中的属性的实现@Transactional:该组件就会被解析加载为对应的对象。

埃泽漫笔 1065

spring事务源码

spring事务的源码解析

qq_74080022的博客 1092

Spring 事务源码分析

总结:阅读了 Sping 事务源码之后,我们熟悉了事务的执行流程,也可以理解 Sping 事务的传播行为的作用,通过源码我们可以知道 PROPAGATION_NESTED 隔离级别并不是真正的新开了一个事务,只是自己新建了保存点,并没有新建事务,因为自己新建了事务保存点,所以自己提交回滚都不会影响外层事务,同样因为使用的是同一个事务,外层事务回滚内层事务也会回滚,这些知识不通过阅读源码是很难知道的,希望可以帮助到有需要的小伙伴。本篇我们将从源码来分析 Spring 声明式事务的执行流程。

weixin_42118323的博客 1831

Spring源码解析:Spring 事务

我们再⼩节⼀下,⽂章先介绍了事务的使⽤示例,以及事务的执⾏流程。先匹配出 model 对象所有关于事务的切⾯列表,并将匹配成功的事务属性保存到缓存;从缓存取出事务属性,然后创建、启动事务,执⾏业务逻辑,最后提交或者回滚事务。

Java技术攻略的博客 462

Spring事务源码解读

一、Spring事务使用 1.通过maven方式引入jar包 <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version> </dependency> <dependency> <group

Trouvailless的博客 1389

Spring源码之事务处理

spring 事务处理的源码阅读

何忆清风 4万+
上一篇: Netty精讲(二)编解码器、粘包拆包、心跳检测、零拷贝
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值