在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. 解决axios异步问题

  2. css简单实现带箭头的边框

    原文地址 https://tianshengjie.cn/artic... css简单实现带箭头的边框 普通边框 <style> .border { width: 100px; heigh ...

  3. leetcode-mid-array-5. Longest Palindromic Substring

    mycode   12.51% class Solution(object): def longestPalindrome(self, s): """ :type s: ...

  4. ora600

    4节点RAC:版本oracle11.2.0.4 22:20——23:40发生ora600 alert日志: Errors in file /u01/app/oracle/diag/rdbms/orcl ...

  5. 十、补充数据类型set

    set:无顺序的不重复的集合 list---允许重复,修改tuple--允许重复,不能修改 set----不允许重复的集合例子: s=set()print s l1=[11,22,33,22,11]l ...

  6. day57——ajax之初体验

    转行学开发,代码100天——2018-05-12 今天是一个特别的日子——首先是母亲节,在此也祝福亲爱的妈妈健康长寿.其次今天是汶川大地震10周年,10年过去了,经历过苦难的人更加坚毅勇敢地面向未来! ...

  7. 关于崩溃报告的日志以及dump文件

    在用户使用软件的过程当中突然产生软件崩溃的问题,必须采取相关的措施去拦截崩溃产生的原因,这有助于程序员解决此类崩溃的再次发生.特别是有些难以复现的崩溃,不稳定的崩溃,更有必要去调查崩溃产生的原因.一般 ...

  8. 阶段1 语言基础+高级_1-2 -面向对象和封装_16this关键字的作用

    this主要是在重名的情况下 ,起到区分的效果 新建demo04的包,里面新建类Person 通过this.进行区分 this关键字可以解决重名 分不开的问题 这里的person调用的sayHello ...

  9. 如何通过脚本实现显示版本号、CPU、硬盘和内存条大小

    COLOR="\033[1;$[RANDOM%7+31]m"     COLOR1="\033[1;$[RANDOM%7+31]m"COLOR2="\ ...

  10. vue项目 多文件上传并显示在页面上

    <template> <label for="file" class=" btn btn-default" style="borde ...