Spring事务原理?事务在方法间如何传播?为什么会失效?
推荐学习
- 疯狂膜拜!阿里出品Spring Security王者晋级文档
- 肝了十天半月 , 献上纯手绘“Spring/Cloud/Boot/MVC”全家桶脑图
文章插图
前言事务我们都知道是什么 , 而Spring事务就是在数据库之上利用AOP提供声明式事务和编程式事务帮助我们简化开发 , 解耦业务逻辑和系统逻辑 。 但是Spring事务原理是怎样?事务在方法间是如何传播的?为什么有时候事务会失效?接下来咱就一一解答~重点分析Spring事务源码 , 让我们彻底搞懂Spring事务的原理 。
正文XML标签的解析【Spring事务原理?事务在方法间如何传播?为什么会失效?】
配置过事务的应该都不陌生 , 上面这个配置就是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 security CSRF 跨域访问限制问题
- Spring Boot搭建的一个在线文件预览系统
- 面试官:问你一个,Spring事务是如何传播的?
- 对Spring MVC接口进行Mock测试
- 随机森林(Random Forest)算法原理
- Spring Cloud Alibaba之 Sentinel
- SpringBoot+MyBatis+MySQL读写分离实现
- C/C++协程学习笔记丨C/C++实现协程及原理分析视频
- SpringBoot构造流程源码分析:Web应用类型推断
- 搭建私有Sentry日志收集系统并集成到springboot