Spring声明式事物原理分析
基础准备 pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springannotation.test</groupId> <artifactId>NddSpring</artifactId> <version>1</version> <dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.12.RELEASE</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.44</version> </dependency> </dependencies> </project>
基础准备 配置
package com.lkd.config;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.lkd.aop.LogAspects;
import com.lkd.aop.MathCalculator;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.lkd")
@EnableTransactionManagement
public class AopConfig {
@Bean
public MathCalculator calu() {
return new MathCalculator();
}
@Bean
public LogAspects aspects() {
return new LogAspects();
}
@Bean
public Object obj() {
return new Object();
}
@Bean
public DataSource student() throws Exception {
ComboPooledDataSource student =new ComboPooledDataSource();
student.setUser("root");
student.setPassword("123456");
//student.setDriverClass("com.mysql.jdbc.driver");
student.setDriverClass("com.mysql.jdbc.Driver");
student.setJdbcUrl("jdbc:mysql://localhost:3306/mytransction");
return student;
}
@Bean
public DataSource student2() throws Exception {
ComboPooledDataSource student =new ComboPooledDataSource();
student.setUser("root");
student.setPassword("123456");
//student.setDriverClass("com.mysql.jdbc.driver");
student.setDriverClass("com.mysql.jdbc.Driver");
student.setJdbcUrl("jdbc:mysql://localhost:3306/myt2");
return student;
}
@Bean
public JdbcTemplate jdbcTemplate1(DataSource student) {
return new JdbcTemplate(student);
}
@Bean
public JdbcTemplate jdbcTemplate2(DataSource student2) {
return new JdbcTemplate(student2);
}
@Bean
public MysqlDataSource student3() {
MysqlDataSource student = new MysqlDataSource();
student.setUser("root");
student.setPassword("123456");
//student.setDriverClass("com.mysql.jdbc.driver");
student.setURL("jdbc:mysql://localhost:3306/myt2");
return student;
}
@Bean
public JdbcTemplate jdbcTemplate3(DataSource student3) {
return new JdbcTemplate(student3);
}
@Bean
public PlatformTransactionManager txmanager() throws Exception {
return new DataSourceTransactionManager(student());
}
}
开始分析
@EnableTransactionManagement 开启声明式事务功能
为容器中导入TransactionManagementConfigurationSelector,它又会容器中导入 AutoProxyRegistrar(imp BeanDefinitionRegister)其作用为容器注入 InfrastructureAdvisorAutoProxyCreator 自动代理增强组件;利用后置处理器机制在对象创建以后
包装对象返回一个代理对象;
ProxyTransactionManagementConfiguration 给容器注入事物增强器 (解析注解) AnnotationTransactionAttributeSource;给容器中注入事物拦截器 TransactionInterceptor ,保存了事物属性信息包括事务管理器
a: 先获取事物属性TransactionAttribute,再获取PlatformTransactionManager平台事物管理器,未在Transctional注解中指定事物,则会在ioc容器中根据PlatFormTransctionManager类型的事物管理器对象
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { /** * {@inheritDoc} * @return {@link ProxyTransactionManagementConfiguration} or * {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and * {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively */ @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { case PROXY: return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } }
执行过程中出现异常
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);//出现异常进行回滚
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
return retVal;
}
总结 : 事物实际上在spring维度是对AOP的应用,掌握了Aop原理,事物则会理解起来贼tm容易。如果AOP不清楚的可以看我Aop解析。
https://www.cnblogs.com/leaveast/p/10829917.html
浙公网安备 33010602011771号