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
Spring声明式事物原理分析的更多相关文章
- spring 声明式事务原理解读
在Spring中,声明式事务是通过事务属性(transaction attribute)来定义的.事务属性描述了事务策略如何应用到方法上.事务属性包含5个方面: 传播行为 隔离级别 是否只 ...
- 浅谈spring 声明式事物
此处主要讲讲事物的属性. 事物属性包含了五个方面: 1.传播行为 2.隔离规则 3.回滚规则 4.事物超时 5.是否只读 一.传播行为 事务的第一个方面是传播行为(propagation behavi ...
- Spring学习之声明式事物管理
public List<Student> selectStudent() { Student s = new Student(); s.setName("zhengbin&quo ...
- SSH学习——声明式事物管理(Spring)
1.什么是事物? 事务是一组操作的执行单元,相对于数据库操作来讲,事务管理的是一组SQL指令,比如增加,修改,删除等,事务的一致性,要求,这个事务内的操作必须全部执行成功,如果在此过程种出现了差错,比 ...
- Spring声明式事务管理基于@Transactional注解
概述:我们已知道Spring声明式事务管理有两种常用的方式,一种是基于tx/aop命名空间的xml配置文件,另一种则是基于@Transactional 注解. 第一种方式我已在上文为大 ...
- spring5 源码深度解析----- @Transactional注解的声明式事物介绍(100%理解事务)
面的几个章节已经分析了spring基于@AspectJ的源码,那么接下来我们分析一下Aop的另一个重要功能,事物管理. 事务的介绍 1.数据库事物特性 原子性多个数据库操作是不可分割的,只有所有的操作 ...
- spring声明式事务管理总结
事务配置 首先在/WEB-INF/applicationContext.xml添加以下内容: <!-- 配置事务管理器 --> <bean id="transactionM ...
- Spring声明式事务配置管理方法
环境配置 项目使用SSH架构,现在要添加Spring事务管理功能,针对当前环境,只需要添加Spring 2.0 AOP类库即可.添加方法: 点击项目右键->Build Path->Add ...
- 161117、使用spring声明式事务抛出 identifier of an instance of
今天项目组有成员使用spring声明式事务出现下面异常,这里跟大家分享学习下. 异常信息: org.springframework.orm.hibernate3.HibernateSystemExce ...
随机推荐
- 操作系统OS,Python - 协程(Coroutine)
留坑 参考: https://en.wikipedia.org/wiki/Coroutine https://zh.wikipedia.org/wiki/%E5%8D%8F%E7%A8%8B http ...
- 【协作式原创】查漏补缺之Go的slice基础和几个难点
[转载]队友博客 Q: 为啥要字节对齐的 https://www.nowcoder.com/discuss/57978 TODO: Q: go反汇编指令 go tool compile -S plan ...
- nginx的access的阶段的access模块、auth_basic模块、auth_request模块及satisfy指令介绍
access 模块 示例从上向下匹配 location / { deny 192.168.1.1; allow 192.168.1.0/24; allow 10.1.1.0/16; allow 200 ...
- vue配置、创建项目及运行
首先安装Node.js, npm i -g cnpm --registry=https://registry.npm.taobao.org 安装镜像 安装以后cnpm可以代替npm cnpm i -g ...
- 借助工具解决DNS污染
我第一次接触到DNS污染,是在GitHub上面进行学习的时候,发现头像加载出问题,加载失败,而且文档里面的图片也无法显示...... 百度了很多内容,差不多都试了一下,最终选择了使用DNS工具去解决 ...
- 【转】python中的闭包详细解析
一.什么是闭包? 如果一个内嵌函数访问外部嵌套函数作用域的变量,并返回这个函数,则这个函数就是闭包 闭包必须满足三个条件: 1. 必须有一个内嵌函数 2. 内嵌函数必须引用外部嵌套函数中的变量 ...
- 【PAT甲级】1032 Sharing (25 分)
题意: 输入两个单词的起始地址和一个正整数N(<=1e5),然后输入N行数据,每行包括一个五位数的字母地址,字母和下一个字母的地址.输出这两个单词的公共后缀首字母的地址,若无公共后缀则输出-1. ...
- uniapp - 导航切换(样式)
<view class="text-area" v-for="(menu,i) in menus" :key="i" v-show=& ...
- JS中字符串的编码 解码
DEPTNAME 是一个字符串 编码: DEPTNAME = encodeURI(encodeURI(DEPTNAME)); 解码: DEPTNAME = decodeURI(DEPTNAME,&qu ...
- Python - Mro
参考 https://stackoverflow.com/questions/2010692/what-does-mro-do http://python.jobbole.com/85685/ 问题: ...