Spring事务原理?事务在方法间如何传播?为什么会失效?
推荐学习
- 疯狂膜拜!阿里出品Spring Security王者晋级文档
- 肝了十天半月 , 献上纯手绘“Spring/Cloud/Boot/MVC”全家桶脑图
文章插图
前言事务我们都知道是什么 , 而Spring事务就是在数据库之上利用AOP提供声明式事务和编程式事务帮助我们简化开发 , 解耦业务逻辑和系统逻辑 。 但是Spring事务原理是怎样?事务在方法间是如何传播的?为什么有时候事务会失效?接下来咱就一一解答~重点分析Spring事务源码 , 让我们彻底搞懂Spring事务的原理 。
正文XML标签的解析
配置过事务的应该都不陌生 , 上面这个配置就是Spring开启事务注解(@Transactional)支持的配置 , 而看过我之前文章的应该知道 , 这个带前缀的标签叫自定义标签 , 我在之前的文章也分析过自定义标签的解析过程 , 所以这里我直接找到对应的handler:public class TxNamespaceHandler extends NamespaceHandlerSupport { static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager"; static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager"; static String getTransactionManagerName(Element element) {return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME); } @Override public void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser()); }}
可以看到对应的注解解析器就是AnnotationDrivenBeanDefinitionParser类 , 在该类中一定会有一个parse方法: public BeanDefinition parse(Element element, ParserContext parserContext) {registerTransactionalEventListenerFactory(parserContext);String mode = element.getAttribute("mode");if ("aspectj".equals(mode)) {// mode="aspectj"registerTransactionAspect(element, parserContext);if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {registerJtaTransactionAspect(element, parserContext);}}else {// mode="proxy"AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);}return null; }
首先拿到mode属性的值判断是使用AspectJ生成代理还是JDK生成代理 , 这里我们主要看proxy模式 , 进入configureAutoProxyCreator方法:public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {// 注册AOP的入口类AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {Object eleSource = parserContext.extractSource(element);// Create the TransactionAttributeSource definition.// @Transactional注解的属性封装RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);// Create the TransactionInterceptor definition.// AOP执行链RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);interceptorDef.setSource(eleSource);interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);// 拿到transaction-manager属性的值registerTransactionManager(element, interceptorDef);interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);// Create the TransactionAttributeSourceAdvisor definition.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+Angular9+MySQL开发平台
- 苹果联合创始人的手绘Apple II电路原理图拍出63万美元高价
- C/C++协程学习笔记丨C/C++实现协程及原理分析视频
- 别不拿GateWay当回事,SpringCloud告诉你错了
- web 安全之 Spring Security 入门教程
- 前端路由简介以及vue-router实现原理
- Spring Application实例化流程和构造方法参数
- SpringBoot常用注解
- 抄github上的golang代码被坑后,弄懂了gin的原理
- 物理精神,科技创新的第一性原理是什么?