本文将对Spring在整合Hibernate事务方面的源码作一下初步的解析,特别是Spring对线程、事务、Hibernate Session三者的绑定关系。(注:本文基于目前最新的Spring 3.1.2 RELEASE 版本的源码进行分析)本文原文链接http://blog.csdn.net/bluishglc/article/details/7774131 转载请注明出处。
众所周知,Spring的事务控制是基于AOP来实现的,而AOP的实现又依赖于JDK的动态代理或者是aspectj,一般情况下,遵循“基于抽象编程”的教义,Service层和DAO层都以接口+实现类的方式提供,此时,Spring会使用动代理来实现AOP拦截,我们的分析也是基于这种拦截方式展开的。那么下面,我们就假设:一个声明了事务的方法(如某个Service的方法)被调用了,在调用时,该方法将被拦截,执行拦截的方法是:
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(Object, Method, Object[])
该方法主要是把所要调用的目标方法和需要施加的操作(即AOP中的Interceptor/Advice)粘合成一个ReflectiveMethodInvocation实例去执行。ReflectiveMethodInvocation最终会调用
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(MethodInvocation)
进行有关事务的操作。作为一个环绕切面,该方法主要负责在目标方法执行前开始一个事务,在方法执行结束后提交事务。
我们先来深入了解一下事务是如何创建的。从方法createTransactionIfNecessary()上可以看到,创建事务的主要方法是:
org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(TransactionDefinition)
作为抽象类的方法,getTransaction()只处理了一些通用性的检查和设置,实质性的创建事务和开启事务操作都是通过分别调用抽象方法:
org.springframework.transaction.support.AbstractPlatformTransactionManager.doGetTransaction()
和
org.springframework.transaction.support.AbstractPlatformTransactionManager.doBegin(Object,TransactionDefinition)
来完成的,也就是说这些关键性的工作必须由各具体事务管理器来实现,对于hibernate的事务管理器来说,获取事务对象的方法如下:
开始事务的方法如下:
以上是关于事务开始部分的代码,下面我们来看一下事务提交时的代码:
同样的,从方法commitTransactionAfterReturning()我们可以看出执行事务提交的方法主要通过回调
org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(DefaultTransactionStatus)
来实现的。
补充:
关于方法
org.springframework.transaction.support.TransactionSynchronizationManager.getResource(Object key)
如该方法的注释所说,它主要是通过给定的key找到对应的资源,特别之处是这些资源实例是绑定在线程上的,也就是spring保证一个线程上一个key对应一个资源实例,不同的线程上绑定的是不同的资源实例。对应到Hibernate上来说,key是sessionFactory,资源是sessionHolder!
近期其他博文:
数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量
数据库分库分表(sharding)系列(二) 全局主键生成策略
数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示
-
顶
-
踩
-
猜你在找
7楼 DIrtyG2015-11-02 14:10发表 [回复]-
-
太厉害
6楼 Naruto42013-11-16 11:40发表 [回复]-
-
一直有个疑问,今天遇到大神了。想问一下,在声明式事务中为什么@Transactional注解打在Controller层的方法上不起作用啊?
Re: line_lin2014-03-06 21:56发表 [回复]-
-
回复Naruto4:这个是可以有的,如果你确定你的事务管理的配置对了的话,那么看下你的controller的方法的修饰符是不是public的,文档里说如果不是public的话,那么@Transactional标签是不报错也不起作用的。
Method visibility and @Transactional
When using proxies, you should apply the @Transactional annotation only to methods with
public visibility. If you do annotate protected, private or package-visible methods with the
@Transactional annotation, no error is raised, but the annotated method does not exhibit the
configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate
non-public methods.
5楼 做人厚道2013-09-19 18:04发表 [回复]-
-
藏起来慢慢消化。
4楼 IFULEYOU492013-04-11 16:56发表 [回复]-
-
为啥还要一个conncectionHolder呢
3楼 miligu2012-08-01 22:43发表 [回复] [引用] [举报]-
-
藏起来慢慢看。。。
2楼 manaduona1232012-07-26 11:51发表 [回复]-
-
讲得太深奥了,搞得我以为是翻译过来的文章
1楼 -_-快乐2012-07-24 15:46发表 [回复]-
-
不错