这里讲述的是以@Transactional注解方式配置Spring事务的原理。

我们启用事务注解的时候,往往配置如下:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" />
</bean><tx:annotation-driven transaction-manager="txManager" />

在Spring中,annotation-driven是用来开启注解支持的,前面添加名字空间,如tx:或者mvc:之类的,后面可以选填一些属性,这是我们需要了解的,具体属性值情况如下:

1、transaction-manager:指定到现有的PlatformTransactionManager bean的引用,通知会使用该引用。默认值为"transactionManager" 
2、mode:指定Spring事务管理框架创建通知bean的方式。可用的值有proxy和aspectj。默认值为proxy,表示通知对象是个JDK代理;后者表示Spring AOP会使用AspectJ创建代理。 
3、order:指定创建的切面的顺序。只要目标对象有多个通知就可以使用该属性。 
4、proxy-target-class:该属性如果为true就表示你想要代理目标类而不是bean所实现的所有接口。默认值为"false" 。

先来看看下面的Spring是如何处理<tx:annotation-driven transaction-manager="txManager" />标签的,先是org.springframework.beans.factory.xml.BeanDefinitionParserDelegate来处理标签,通过parseCustomElement()方法找到对应名字空间处理器,也即org.springframework.transaction.config.TxNamespaceHandler这个类来处理tx名字空间的标签的:

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);}@Overridepublic void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());}
}

真正处理的类型是org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser,具体的方法如下:

@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {registerTransactionalEventListenerFactory(parserContext);String mode = element.getAttribute("mode");if ("aspectj".equals(mode)) {// mode="aspectj"registerTransactionAspect(element, parserContext);}else {// mode="proxy"AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);}return null;
}

这里我们使用的是默认mode="proxy",也就是使用jdk提供的代理方式,这个函数始终返回null这点要注意。那么现在就要看看AnnotationDrivenBeanDefinitionParser中的静态内部类中的configureAutoProxyCreator()方法做了什么,这里也可以借鉴下使用静态内部类的情景,这个静态内部类只有一个静态方法,显然作者这里更多的体现的是封装思想以及面向对象编程思想。

private static class AopAutoProxyConfigurer {public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {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.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.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);// 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);}}
}

这里看到通过硬编码的方式实例化了几个类到IOC容器中。

Spring事务处理流程相关推荐

  1. Spring事务处理流程和原理(动脑学院笔记)

    一.事务理论 1.事务的特性  2.事务的隔离级别 3.事务的传播   4.利用数据库事务实现应用事务控制 要求:同一个事务需要同一个库的同一个连接.  5.单一数据源,如何让事务的所有操作使用同一连 ...

  2. Spring事务处理之 编程式事务 和 声明式事务

    对事务概念还不了解的可以先看一下 MySQL事务管理(初步了解) 这篇文章 !!! Spring事务管理学习步骤: 1.掌握Spring事务属性 2.掌握Spring事务核心API 3.掌握Sprin ...

  3. 分布式锁 动态代理 Java数据结构List,Set,Map,Spring执行流程,Spring MVC组件

    这里对今日的内容进行总结: 分布式锁具备的条件: 具备的条件: 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行. 高可用的获取锁与释放锁. 高性能的获取锁与释放锁. 具备可重入的特 ...

  4. Java框架之SpringMVC 05-拦截器-异常映射-Spring工作流程

    Java框架之SpringMVC 05-拦截器-异常映射-Spring工作流程 参考文章: (1)Java框架之SpringMVC 05-拦截器-异常映射-Spring工作流程 (2)https:// ...

  5. Spring Batch流程介绍

    Spring Batch流程介绍: 上图描绘了Spring Batch的执行过程.说明如下: 每个Batch都会包含一个Job.Job就像一个容器,这个容器里装了若干Step,Batch中实际干活的也 ...

  6. spring启动流程(一):启动流程概览

    1. spring 启动流程概览 在前面 demo 的 main()方法中,有这么一行: ApplicationContext context =new AnnotationConfigApplica ...

  7. 初次创建spring boot流程和注意事项

    新手初次创建spring boot流程和注意事项 一.项目整合与部署存在的问题 1.1 SSM手动整合存在的问题 SSM整合步骤多.配置繁琐 项目进行服务器部署步骤繁琐 1.2 如何简化这些繁琐的配置 ...

  8. Spring事务处理浅析

    类层次结构 在Spring的事务处理模块中.可以看到的类层次结构如图: 可以看到,Spring事务处理模块是通过AOP功能来实现声明式事务处理的,比如事务属性的配置和读取,事务对象的抽象等.因此,在S ...

  9. 简单理解Spring getBean流程

    本文直接讲述流程,不贴代码,全是干货,面试必看,口口相传. 熟悉Spring启动流程的同学应该清楚,refresh()是最为重要的关键方法,其调用的finishBeanFactoryInitializ ...

最新文章

  1. 如何看懂一个深度学习的项目代码
  2. The Constructor with No Arguments
  3. linux ftp 怎么验证,Linux编译安装vsftpd服务器(本地用户验证方式)
  4. mysql系列_Mysql系列(三)—— Mysql字符集和比较规则
  5. 特斯拉完全自动驾驶可能再次涨价 涨至1.4万美元
  6. css分页实例讲解,CSS 分页实例
  7. 搭建一个开发Predix软件的Windows系统(1)准备工作
  8. win10 快捷键大全(集合)
  9. pr中裁剪工具的使用
  10. 《摩根写给儿子的32封信》 03 企业家的资质
  11. centos安装部分开发软件
  12. SSD-caffe踩keng
  13. 万丈高楼平地起 功夫不负有心人
  14. 导出备忘录Word文档
  15. Pyhton3 下载Telegram 频道数据
  16. 沐风老师3dsMax手把手教系列:椅子建模(款式001)
  17. sUploadDir
  18. filezilla 后文件传输失败_filezilla严重文件传输错误技术分享
  19. rpc协议微服务器,go微服务之rpc:hprose服务端
  20. 精准解决IDEA中文字体大小不一 奇奇怪怪

热门文章

  1. POJ 3342- Party at Hali-Bula (树形dp+判断是否唯一)
  2. Python获取类名的字符串格式
  3. 魔兽怎么查服务器状态,如何查看魔兽世界服务器状态(查看游戏服务器状态的技巧)...
  4. 支付宝核心是oracle吗,李铮 - 支付宝核心账务去Oracle实践
  5. 表达式计算器 ExpressionRunner
  6. 关于水仙花数及用Python函数解析水仙花数算法
  7. 从Java Future 到 Guava ListenableFuture实现异步非阻塞调用
  8. 微信为啥不丢“离线消息”?
  9. IAPCRAZY破解使用方法
  10. 染布厂ERP新员工培训流程(中山宏瑞计算机科技有限公司编辑)