在Spring中把非功能性的事物管理代码以切面的形式进行管理,只需要声明事物即可启用事物管理。

本质:最终执行的还是java.sql.Connection的setAutoCommit(),commit(),rollback()方法。

事物管理器接口:PlatformTransactionManager.java

package org.springframework.transaction;

public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}

事物管理器实现:DataSourceTransactionManager.java

主要操作的是DataSource

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean {
private DataSource dataSource;
public DataSourceTransactionManager(DataSource dataSource) {
this();
this.setDataSource(dataSource);
this.afterPropertiesSet();
}
// 提交的实现
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
this.logger.debug("Committing JDBC transaction on Connection [" + con + "]");
} try {
con.commit();
} catch (SQLException var5) {
throw new TransactionSystemException("Could not commit JDBC transaction", var5);
}
} // 回滚的实现
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
this.logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
} try {
con.rollback();
} catch (SQLException var5) {
throw new TransactionSystemException("Could not roll back JDBC transaction", var5);
}
}
}

事物定义:TransactionDefinition.java

package org.springframework.transaction;

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;
int PROPAGATION_NESTED = 6;
// 隔离级别
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
int TIMEOUT_DEFAULT = -1; int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
String getName();
}

事物状态:TransactionStatus.java

public interface TransactionStatus extends SavepointManager, Flushable {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}

事物拦截器:TransactionInterceptor.java

会拦截声明@Transaction注解的方法和类,以及通过

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
public TransactionInterceptor() {
}
public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
this.setTransactionManager(ptm);
this.setTransactionAttributes(attributes);
}
public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
this.setTransactionManager(ptm);
this.setTransactionAttributeSource(tas);
} public Object invoke(final MethodInvocation invocation) throws Throwable {
Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
} private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeObject(this.getTransactionManagerBeanName());
oos.writeObject(this.getTransactionManager());
oos.writeObject(this.getTransactionAttributeSource());
oos.writeObject(this.getBeanFactory());
} private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
this.setTransactionManagerBeanName((String)ois.readObject());
this.setTransactionManager((PlatformTransactionManager)ois.readObject());
this.setTransactionAttributeSource((TransactionAttributeSource)ois.readObject());
this.setBeanFactory((BeanFactory)ois.readObject());
}
}

事物的执行过程:

事物的四大特性ACID

1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。  

2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。  

3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。  

4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

事物的隔离级别

  1. RU:READ_UNCOMMITTED:未提交读

    • 一个事物操作后回滚,导致另一事物读取的数据和数据库中的数据不一致。
  2. RC:READ_COMMITTED:提交读
    • 一个事物操作后提交,导致另一个事物在前一次事物提交前和提交后读取的数据不一致,不能防止重复读。
  3. RR:REPEATABLE_READ:可重复读:读数据加悲观锁,例如 select ... form ... for update
  4. SERIALIZABLE:串行化:串行化,最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了 。

事物的传播行为

常用的传播行为:

  1. REQUIRED:事物存在加入事物,事物不存在则创建一个事物。

  2. REQUIRED_NEW:事物不管是否存在,都创建一个新的事物,上层事物挂起。

  3. SUPPORTS:支持事物,但是有事物存在,才会加入到事物中,没有事物存在不会创建事物,运行在无事物中。

  4. NOT_SUPPORTS:不支持事物,如果存在事物,当前事物被挂起。

参考:https://blog.csdn.net/weixin_39625809/article/details/80707695

避免 Spring 的 AOP 的自调用问题

在 Spring 的 AOP 代理下,只有目标方法由外部调用,目标方法才由 Spring 生成的代理对象来管理,这会造成自调用问题。若同一类中的其他没有@Transactional 注解的方法内部调用有@Transactional 注解的方法,有@Transactional 注解的方法的事务被忽略,不会发生回滚。

解决方案:

<tx:annotation-driven mode="aspectj" /> <!-- 指定模式 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect"
factory-method="aspectOf">
<property name="transactionManager" ref="transactionManager" />
</bean>

AnnotationDrivenBeanDefinitionParser的作用分析

public BeanDefinition parse(Element element, ParserContext parserContext) {
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
if ("aspectj".equals(mode)) {//解决自调用问题
// mode="aspectj"
registerTransactionAspect(element, parserContext);
}
else {
// 默认为proxy模式
// 所以要执行该句
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}

AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
// 在5)中单独分析该句代码的功能
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); // txAdvisorBeanName值为 org.springframework.transaction.config.internalTransactionAdvisor
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element); // 1.注册类AnnotationTransactionAttributeSource到Spring中
RootBeanDefinition sourceDef = new RootBeanDefinition(
"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef); // 2.注册类TransactionInterceptor到Spring中
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registerTransactionManager(element, interceptorDef);
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef); // 2.注册类BeanFactoryTransactionAttributeSourceAdvisor到Spring中
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
parserContext.registerComponent(compositeDef);
}
}

Spring的事物原理的更多相关文章

  1. Spring事物原理完全解析

    事务是什么?了解事务的原理吗?说下Spring的事务原理,能自己实现Spring事务原理吗?先自我检测下这些知识掌握了吗.那么接下来一起看下与Spring相关的事务 概念 事务具有ACID特性. 是指 ...

  2. spring的事物实现

    Spring的事物主要有三个接口 PlatformTransactionManager. 根据TransactionDefinition配置的事物信息创建事物 TransactionDefinitio ...

  3. 【Spring】Spring AOP实现原理

    Spring AOP实现原理 在之前的一文中介绍过Spring AOP的功能使用,但是没有深究AOP的实现原理,今天正好看到几篇好文,于是就自己整理了一下AOP实现的几种方式,同时把代理模式相关知识也 ...

  4. Spring AOP 实现原理

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...

  5. spring ioc aop 原理

    spring ioc aop 原理 spring ioc aop 的原理 spring的IoC容器是spring的核心,spring AOP是spring框架的重要组成部分. 在传统的程序设计中,当调 ...

  6. spring容器IOC原理解析

    原理简单介绍: Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的bean,然后通过反射将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这些bean ...

  7. struts1,struts2,hibernate,spring的运行原理结构图

    一.struts1运行原理 1.初始化:struts框架的总控制器ActionServlet是一个Servlet,它在web.xml中配置成自动启动的Servlet,在启动时总控制器会读取配置文件(s ...

  8. Spring的IOC原理[通俗解释一下]

    Spring的IOC原理[通俗解释一下] 1. IoC理论的背景我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑. 图 ...

  9. 何为代理?jdk动态代理与cglib代理、spring Aop代理原理浅析

    原创声明:本博客来源为本人原创作品,绝非他处摘取,转摘请联系博主 代理(proxy)的定义:为某对象提供代理服务,拥有操作代理对象的功能,在某些情况下,当客户不想或者不能直接引用另一个对象,而代理对象 ...

随机推荐

  1. Linux内核调试方法总结之ptrace

    ptrace [用途] 进程跟踪器,类似于gdb watch的调试方法 [原理][详细说明参考man ptrace帮助文档] ptrace系统调用主要是父进程用来观察和控制子进程的执行过程.检查并替换 ...

  2. (转)sql server 事务与try catch

    本文转载自:http://www.cnblogs.com/sky_Great/archive/2013/01/09/2852417.html sql普通事务 begin transaction tr ...

  3. JSON基础,简单介绍

    JSON(JavaScript Object Notation(记号.标记)) 是一种轻量级的数据交换格式.它基于JavaScript(Standard ECMA-262 3rd Edition - ...

  4. ES6标准入门 第二章:块级作用域 以及 let和const命令

    一.块级作用域 1.为什么需要块级作用域? ES5中只有全局作用域和函数作用域,带来很多不合理的场景. (1)内层变量可能会覆盖外层变量: var tem = new Date(); function ...

  5. vue组件兄弟间通信

    四.兄弟组件间通信(event) 借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发 var bus = new Vue(); bus.$emit()bus.$on() 熊 ...

  6. 【EWM系列】SAP 关于EWM的WT增强简介

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP 关于EWM的WT增强简介   ...

  7. State Function Approximation: Linear Function

    In the previous posts, we use different techniques to build and keep updating State-Action tables. B ...

  8. Tesseract5.0训练字库,提高OCR特殊场景识别率(一)

    0.目标 很多特殊场景,原生的字库识别率不高,这时候就需要根据需求自己训练字库生成traineddata文件. 一.前期准备工作 1.安装jdk   用于运行jTessBoxEditor 2.安装jT ...

  9. C++学习笔记(六)--结构体

    1.一种自定义的类型--结构体定义: struct 结构体名称 { //成员表列也称作域 还可以包括函数,即函数成员,不过一般结构体类型中不包含,而是放在类中. 类型名 成员名; };这种结构体类型类 ...

  10. new String创建了几个对象

    String str = new String(“abc”)  到底创建了几个对象? 首先String str是定义了一个字符串变量,并未产生对象,=不产生对象,那么只有后面的new String(& ...