Spring 事务执行过程源码解析

引言

概述: AOP系列文章:
【1】Spring Aop初始化源码分析
【2】Spring AOP创建代理对象源码解析
【3】Spring AOP 链式调用过程源码解析
【4】Spring 事务执行过程源码解析

1 工程

在这里插入图片描述

1.1 数据库

在这里插入图片描述

CREATE TABLE `t_student` (
  `c_id` int(11) NOT NULL AUTO_INCREMENT,
  `c_name` varchar(255) DEFAULT NULL,
  `c_age` int(12) DEFAULT NULL,
  PRIMARY KEY (`c_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

1.2 pom

 <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring.version>5.2.8.RELEASE</spring.version>
    </properties>

    <dependencies>
        <!--上下文-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${
    
    spring.version}</version>
        </dependency>
        <!--切面-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${
    
    spring.version}</version>
        </dependency>
        <!--事务-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${
    
    spring.version}</version>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${
    
    spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
        <!-- 日志相关依赖 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.10</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!--测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        <!--数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
    </dependencies>

1.3 SpringConfig

@Configuration
@EnableTransactionManagement
public class SpringConfig {
    
    
    //创建数据源
    @Bean
    public DataSource dataSource() throws PropertyVetoException {
    
    
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        return dataSource;
    }

    /**
     *  JDBC
     */
    @Bean
    public JdbcTemplate jdbcTemplate() throws PropertyVetoException{
    
    
        return new JdbcTemplate(dataSource());
    }

    /**
     * 配置事务管理器
     */
    @Bean
    public TransactionManager platformTransactionManager(DataSource dataSource) throws PropertyVetoException {
    
    
        return new DataSourceTransactionManager(dataSource);
    }
}

1.4 Service

public interface StudentService {
    
    


    void insertStudent();

}

@Service
public class StudentServiceImpl implements StudentService {
    
    

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    @Override
    public void insertStudent() {
    
    
        String sql = "insert into `t_student` (c_name, c_age) values(?,?)";
        jdbcTemplate.update(sql, "张三", 18);
    }


}


1.5 Test

public class RoshTest {
    
    

    @Test
    public void mainTest(){
    
    
        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.rosh");

        StudentService studentService = applicationContext.getBean(StudentService.class);

        studentService.insertStudent();

    }

}

1.6 运行

在这里插入图片描述
在这里插入图片描述

2 @EnableTransactionManagement 解析

作用: 开启事务。
在这里插入图片描述

2.1TransactionManagementConfigurationSelector

在这里插入图片描述
在这里插入图片描述

2.2 AutoProxyRegistrar

描述: 该类作向ioc中加入事务执行入口类InfrastructureAdvisorAutoProxyCreator.class,当bean实例化时进行后置加强。
在这里插入图片描述
在这里插入图片描述

2.3 ProxyTransactionManagementConfiguration

描述: 事务核心类,事务其实属于aop的一种典型实现,所以事务加强也有相应的pointcut和advice。

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    
    

	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
    
    
		/**
		 * 创建事务切面,advisor(pointcut advice)
		 */
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		//设置属性
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		//设置advice
		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();
	}


	/**
	 * advice
	 */
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
    
    
		//创建事务切面
		TransactionInterceptor interceptor = new TransactionInterceptor();
		//设置事务处理器
		interceptor.setTransactionAttributeSource(transactionAttributeSource);
		//设置事务管理器
		if (this.txManager != null) {
    
    
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

切点:

在这里插入图片描述
在这里插入图片描述
描述: 是切点就有类匹配和方法匹配,TransactionAttributeSourcePointcut事务切点主要核心是方法匹配,类匹配没怎么干事。
在这里插入图片描述
在这里插入图片描述
描述: 匹配核心源码如下,首先必须是public , 匹配方法上是否带有Transactional注解,最后匹配类上是否带有Transactional注解。

@Nullable
	protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
    
    
		// Don't allow no-public methods as required.

		/**
		 * 【1】 不是public方法不生成代理
		 */
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
    
    
			return null;
		}

		// The method may be on an interface, but we need attributes from the target class.
		// If the target class is null, the method will be unchanged.
		/**
		 * 【2】 获取原始方法
		 */
		Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

		// First try is the method in the target class.
		/**
		 * 【3】 方法匹配,找@Transactional注解,并且把注解属性封装成TransactionAttribute对象
		 */
		TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
		if (txAttr != null) {
    
    
			return txAttr;
		}

		// Second try is the transaction attribute on the target class.
		/**
		 * 【4】 如果方法上没有注解,则判断类上是否有注解
		 */
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
    
    
			return txAttr;
		}

		if (specificMethod != method) {
    
    
			// Fallback is to look at the original method.
			txAttr = findTransactionAttribute(method);
			if (txAttr != null) {
    
    
				return txAttr;
			}
			// Last fallback is the class of the original method.
			txAttr = findTransactionAttribute(method.getDeclaringClass());
			if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
    
    
				return txAttr;
			}
		}

		return null;
	}

advice

advice: 事务加强方法
在这里插入图片描述
在这里插入图片描述

@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
    
    

		// If the transaction attribute is null, the method is non-transactional.

		//获取事务属性
		TransactionAttributeSource tas = getTransactionAttributeSource();

		/**
		 *  【1】 获取方法相关的事务属性(方法匹配pointcut过程)
		 */
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

		/**
		 *  【2】 获取事务管理器
		 */
		final TransactionManager tm = determineTransactionManager(txAttr);

		if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
    
    
			ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
    
    
				if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
    
    
					throw new TransactionUsageException(
							"Unsupported annotated transaction on suspending function detected: " + method +
							". Use TransactionalOperator.transactional extensions instead.");
				}
				ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
				if (adapter == null) {
    
    
					throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
							method.getReturnType());
				}
				return new ReactiveTransactionSupport(adapter);
			});
			return txSupport.invokeWithinTransaction(
					method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
		}

		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
		//获取jointPoint
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
    
    
			// Standard transaction demarcation with getTransaction and commit/rollback calls.

			/**
			 *  【3】 开启事务
			 */
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
    
    
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				/**
				 * 【4】 方法调取
				 */
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
    
    
				// target invocation exception
				/**
				 * 【5】 回滚
				 */
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
    
    
				cleanupTransactionInfo(txInfo);
			}

			if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
    
    
				// Set rollback-only in case of Vavr failure matching our rollback rules...
				TransactionStatus status = txInfo.getTransactionStatus();
				if (status != null && txAttr != null) {
    
    
					retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
				}
			}

			/**
			 * 【7】 提交
			 */
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

3 Debug

3.1 修改代码

在这里插入图片描述

扫描二维码关注公众号,回复: 12915531 查看本文章

3.2 代理对象的创建

描述: 流程和aop一样,在studentServiceImpl实例后置加强时,用所有的advisor匹配当前类、方法,获取当前类有效的advisors,如果advisors不为空,那么创建代理对象,如果当前对象是接口实现类那么使用jdk,否则使用cglib,并把proxyFactory、当前匹配advisors存入代理对象中。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3 事务执行

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34125999/article/details/115220975