spring的事务解析+调用流程
2020-06-29 09:20:37 45 举报
事务初始化,解析.和调用流程
作者其他创作
大纲/内容
JdkDynamicAopProxy.invoke()
ProxyTransactionManagementConfiguration
获取数据源对象,其实就是数据库连接块对象(第一次的时候没有)TransactionSynchronizationManager.getResource(obtainDataSource());
按照常理来说应该是注册这个类作为事务的支撑但是呢我们可以简单看一下这个注册流程。这也可以理之前为啥aop注册支撑的时候整了一个(AUTO_PROXY_CREATOR_BEAN_NAME)的常量InfrastructureAdvisorAutoProxyCreator
具体操作就是把链接写入到ThreadLocal中了
注册事务切面的入口类实际上基本上不会起作用AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
ThreadLocal<TransactionInfo>transactionInfoHolder
@Import(TransactionManagementConfigurationSelector.class)
事务这块的流程感觉比较难梳理。,怼的可能就有点乱了这次我们直接从注解的方式开始。来分析事务的解析和调用流程(另外提一句对于xml方式来说。就是通过在tx包下的spring.handlers中加载的类进行后续初始化和解析工作)因为本质上是aop的扩展。所以初始化的流程包含两部分。一部分注册postProcess,一部分是注册advisor(包含advice以及pointcut)
包含一个TransactionStatus
具体的从连接池获取的Connection对象
determineTransactionAttribute(method);
TransactionInfo
SpringTransactionAnnotationParser主要是这个解析器。负责对transaction注解进行属性的解析和封装最后封装成了RuleBasedTransactionAttribute事务传播propagation 隔离级别isolation
ConnectionHolder
包含了数据库连接ConnectionHolder
doUnbindResource(actualKey);
BeanFactoryTransactionAttributeSourceAdvisor明显是创建事务切面实例
1.生成缓存key,从缓存中看看是否有TransactionAttribute cached = this.attributeCache.get(cacheKey);有就返回。一般都是经过这里返回的
一顿找。如果找不到的话。会去找DEFAULT_TRANSACTION_MANAGER_KEY这个类型的bean去初始化
doSuspend(Object transaction)
最后都没有。表示是REQUIRED的。就直接更改事务状态传回去就可以了
1.事务之间关系的验证,然后是。事务的多种传播途径2.事务的隔离级别3.事务整体的调用流程。包含数据源的释放等操作
newTransaction这个属性等于true表示一个新的事务。后续会根据这个值进行提交回滚等操作。很有用
判断是不是新的事务status.isNewTransaction()
processCommit(defStatus);
这里会去判断当前的事务和当前要开启事务的对象的传播属性会进行不同的操作
线程绑定关系
判断是否有回滚点status.hasSavepoint()
TransactionSynchronizationManager.unbindResource(obtainDataSource());
AutoProxyRegistrar
开启事务tm.getTransaction(txAttr);
this.annotationParsers.add(new SpringTransactionAnnotationParser());这里面有一个parseTransactionAnnotation方法是用来解析transaction注解以及封装他的属性
这个advisor是在这一步里被发现的List<Advisor> advisors = super.findCandidateAdvisors();他的父类其实就是AbstractAdvisorAutoProxyCreator
TransactionAttributeSource完成一个注解解析器的注册
1.获取事务属性对象getTransactionAttributeSource();
根据adviceMode属性进行代理的生成通常会生成的是PROXY
con.rollback();
Object value = map.remove(actualKey);这里的object就是老的链接对象
TransactionInterceptorinvoke(MethodInvocation invocation)
包含
中间方法简单我省略的几步
status.rollbackToHeldSavepoint();按照回滚点回滚
findTransactionAttribute(Class<?> clazz);
开启事务后把事务状态进行一个赋值操作
这一步会去找相应的@Transactional注解的属性,其实在aop对象创建的时候就已经完成了初始化。这里去的时候是从缓存里面拿,简单表述一下
3.获取事务管理器 determineTransactionManager(txAttr);
上述描述了事务注解开启后的相应组件的注册工作,之后同样会在aop扫描切面的时候扫描到注册的事务advisor(AbstractAdvisorAutoProxyCreator..findCandidateAdvisors())然后如同aop一般的操作完成了切面的排序。代理对象的生成。这里还在AopUtils中进行了事务注解的扫描
SpringTransactionAnnotationParser下的parseTransactionAnnotation
包含了一个Object的事务对象
从这个注解的解析开始(他先会被Component族注解解析。之后才会循环解析到下面这个注解)@EnableTransactionManagement
把事务信息对象存进ThreadLocal中,并且从ThreadLocal中拿到老的事务对象\t\ttxInfo.bindToThread();
正常的状态下进行一个事务的提交commitTransactionAfterReturning(txInfo);
设置属性(是否允许嵌套)txObject.setSavepointAllowed(isNestedTransactionAllowed());
PROPAGATION_REQUIRES_NEW,挂起当前事务。重新new一个事务对象出来
事务,线程。数据库连接之间关系的简易关系图
在这个类中会在扫描他的时候循环调用并完成三个bean的注册
在提交的时候先把回滚点都抹掉(第一次事务提交。证明之前的回滚点全部都没有用了)
目标方法调用
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
unexpectedRollback = status.isGlobalRollbackOnly();\t\t\t\t\tstatus.releaseHeldSavepoint();
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
在finally代码块中会进行如下操作cleanupTransactionInfo(txInfo);这个是把之前的事务对象写入到threadlocal中(类似一个栈的操作)
也就是事务对象DataSourceTransactionObjecttransaction
doRollback(status);
只有new的情况下才会提交事务
创建回滚点new DataSourceTransactionObject();
赋值属性,包括设置数据库的隔离级别,关闭自动提交。判断是不是只读事务等操作
万物开端
doGetTransaction();
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
findTransactionAttribute(Method method);
cleanupAfterCompletion(status);事务提交完成之后。要进行资源的释放。和重新建立的绑定关系
PROPAGATION_NESTED嵌套事务的。创建一个回滚点。
determineTransactionAttribute(clazz);
TransactionInterceptor创建一个advice
在新建一个事务的时候会挂起事务suspend(transaction)
实际上就是事务状态对象DefaultTransactionStatus
判断有没有数据库链接。没有就从数据库连接池获取一个 Connection newCon = obtainDataSource().getConnection();之后封装成ConnectionHolder对象写入当前事务中
AutoProxyRegistrar ProxyTransactionManagementConfiguration
当前要开启的事务是PROPAGATION_NEVER即不允许事务。这里会直接抛出异常
1.先进行一个判断。看看你注测的bean中是否有AUTO_PROXY_CREATOR_BEAN_NAME如果有那么就比较他们的顺序如果当前的小于现有的bean就替换掉原来的bean。否则直接返回null
1.获取调用链2.调用proceed3.经过火炬传递到事务处理类
其实感觉现阶段总结起来就是。事务和线程是挂钩的。数据库连接和线程也是挂钩的,在嵌套事务和回滚事务的时候会去获取前一个事务信息对象,并重新建立和线程的绑定关系。老的事务对象在TransactionInfo中的oldTransactionInfo,老的连接对象在DefaultTransactionStatus中suspendedResources
unexpectedRollback = status.isGlobalRollbackOnly();\t\t\t\t\tdoCommit(status);
1.找到他的实现方法2.去看这个目标方法是不是有事务注解3.去看这个目标方法的类是不是有事务注解4.都没有再看原始方法。原始方法的类上
之后老的事务对象就可以从当前事务对象中的oldTransactionInfo中获取。(这里其实有点类似与链表的一个结构。用来以后的事务恢复)
Thread
0 条评论
下一页