http://blog.sina.com.cn/s/blog_8f61307b0100ynfb.html

————————————————————————————————————————————————————————

这篇文章是我从ITeye上复制来的,看了一遍,觉得很深刻,决定把他复制来,对原作者表示感谢。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
本文仅基于3.0+版本作为测试)
假定spring 容器中定义了两个事务管理器:transactionManagerX,transactionManagerY,分管两个数据源datasourceX和datasourceY.
<tx:annotation-driven transaction-manager="transactionManagerX" />
<tx:annotation-driven transaction-manager="transactionManagerY" />
(spring容器中的定义顺序如上)
有如下应用代码:
public interface TestEntityService {
public void methodX();
public void methodY();
}
 
接口实现类1
public class TestEntityServiceImpl implements TestEntityService {
@Resource
private TestEntityDao testEntityDao;//实际操作的是datasourceX.
@Transactional
public void methodX() {
testEntityDao.xxx();
testEntityDao.zzz();
}
public void methodY() {
}
}
 
接口实现类2
public class AnotherTestEntityServiceImpl implements TestEntityService {
@Resource
private TestEntityDao anOtherTestEntityDao;//实际操作的是datasourceY.
@Transactional
public void methodX() {
testEntityDao.mmm();
testEntityDao.nnn();
}
public void methodY() {
}
}
假设方法methodX需要事务控制的,通常我们是直接在方法上添加@Transactional标注,
但是好像spring3.0(具体版本没弄清)之前的Transactional标注不支持区分使用哪个事务管理器。3.0之后的版本Transactional增加了个string类型的value属性来特殊指定加以区分。
例如@Transactional("aaaaa"),即显示的要求spring用id="aaaaa"的事务管理器来管理事务。该属性亦可省略(省略的话用容器中缺省的transactionManager)
对于该属性的用法做了如下测试来
methodX()事务生效测试结果
@Transactional
("transactionManagerX")

 
@Transactional
("transactionManagerY")

 
@Transactional
("transactionManagerZ")
 transactionManagerZ为未定义过的
@Transactional  
TestEntityServiceImpl(实际使用datasourceX)
Y
N
Y
Y
AnotherTestEntityServiceImpl (实际使用datasourceY)
N
Y
N
N
如果调换两个事务管理器在容器中的定义顺序,如
<tx:annotation-driven transaction-manager="transactionManagerY" />
<tx:annotation-driven transaction-manager="transactionManagerX" />
得到的结果
methodX()事务生效测试结果
@Transactional
("transactionManagerX")

 
@Transactional
("transactionManagerY")

 
@Transactional
("transactionManagerZ")
 transactionManagerZ为未定义过的
@Transactional  
TestEntityServiceImpl(实际使用datasourceX)
Y
N
N
N
AnotherTestEntityServiceImpl (实际使用datasourceY)
N
Y
Y
Y

分析结果(其实源码就可以反应出):容器指定一个默认的事务管理器

 
1.当在@Transactional("xxx")中正确指定了需要使用的事务管理器时,事务控制正常。
2.如果@Transactional指定了未定义过的事务管理器,spring以缺省默认的事务管理器来处理。(如果程序正好使用的是缺省事务管理器同一个数据源,事务控制将生效)。
3.如果@Transactional不指定事务管理器,使用缺省。
4.如果@Transactional指定了不匹配的事务管理器(实际用到的数据源和指定的事务管理器控制的数据源不一致),事务控制将失效.
注:spring容器缺省事务管理器:以加载顺序,首先加载的作为缺省。例如
如果

<tx:annotation-driven transaction-manager="transactionManagerX" />
<tx:annotation-driven transaction-manager="transactionManagerY" />
定义在同一个文件中,则第一个transactionManagerX作为缺省。
定义在不同文件,则按文件的加载顺序,首先加载的作为缺省。


议:实际代码中需要用到@Transactional时,即使默认只有一个transactionManager,@Transactional也将其标
明。以提高新增数据源后代码可读性,另外防止定义多个数据源后,以前缺省的不被spring默认为缺省了(比如哪天上线新定义了一个数据源,刚好新定义的
transactionManager被先加载了,那就悲剧了。)

 
 
二.bean的配置使用
容器中加了<tx:annotation-driven >(需要增加一些xsd)之后,需要事务控制的的service,不需要再具体的bean上做其他的配置,例如用代理包装。直接配置即可
<bean id="testEntityService" class="com.xxx.impl.TestEntityServiceImpl"/>
spring将由JdkDynamicAopProxy 生成代理过的类提供使用。
这种用法的效果和下面配置使用效果一样。都是由JdkDynamicAopProxy 生成代理对象提供使用。
我觉得区别是下面的方法在事务控制的代码可读性上不好,因为哪个方法需要事务控制和控制粒度都在配置文件中,和代码分开了。
<bean id="testEntityService3" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
     
<property name="transactionManager" ref="transactionManagerX" />
     
<property name="target">
        
<bean class="com.xxxx.impl.TestEntityServiceImpl" />
     
</property>
     
<property name="proxyInterfaces" value="com.xxxx.TestEntityService"/>
     
<property name="transactionAttributes">
        
<props>
          
<prop key="*">PROPAGATION_REQUIRED</prop>
        
</props>
     
</property>
</bean>
 
方法的可见度和 @Transactional
@Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,请注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。上面的例子中,其实正是 <tx:annotation-driven/>元素的出现 开启 了事务行为。
Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的。
 
实际开发中,多半喜欢将持久化操作的代码集中抽出为另一个方法(因为不想事务被无关的业务代码托的持续太长),然后在抽取出来的方法上加上
@Transactional,这样的结果是被抽离出的代码即使加了事务标记,也根本起不到事务控制的效果(不管是private和public)。
例如:

public class TestEntityServiceImpl implements TestEntityService {
@Resource
private TestEntityDao testEntityDao;//实际操作的是datasourceX.
@Transactional
public void methodX() {
testEntityDao.xxx();
testEntityDao.zzz();
}
public void methodY() {
methodX() 
}
}
如果执行TestEntityService.methodY();事务是不生效的。只有TestEntityService.methodY();才生效。
从spring实现这些的原理(动态代理和aop)上来看,只拦截外部调用,方法的内部调用通常是不被aop支持的。
从网上扒到一篇文章,可以解决这个问题。http://blog.csdn.net/quzishen/archive/2010/08/11/5803721.aspx

spring的annotation-driven配置事务管理器详解的更多相关文章

  1. spring 配置事务管理器

    在Spring中数据库事务是通过PlatformTransactionManager进行管理的,jdbcTemplate是不能支持事务的,而能够支持事务的是org.springframework.tr ...

  2. Spring事务管理(详解+实例)

    1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是 ...

  3. (转)Spring事务管理(详解+实例)

    文章转自:http://blog.csdn.net/trigl/article/details/50968079 写这篇博客之前我首先读了<Spring in action>,之后在网上看 ...

  4. Spring4.X + spring MVC + Mybatis3 零配置应用开发框架搭建详解(1) - 基本介绍

    Spring4.X + spring MVC + Mybatis3 零配置应用开发框架搭建详解(1) - 基本介绍 spring集成 mybatis Spring4.x零配置框架搭建 两年前一直在做后 ...

  5. mybatis事务管理机制详解

    1.mybatis事务的配置和使用 mybatis事务有两种使用方式: (a):使用JDBC的事务管理机制:即使用java.Sql.Connection对象完成对事务的提交,回滚和关闭操作. (b): ...

  6. HTTP属性管理器详解

      1)HTTP Cache Manager 2)HTTP Cookie 管理器 3)HTTP 信息头管理器 4)HTTP 授权管理器 5)HTTP 请求默认值 为什么会有这些http属性的配置元件? ...

  7. tkinter之grid布局管理器详解

    在很久之前,我发过一篇<tkinter模块常用参数>,里面已经几乎涵盖了tkinter的大部分教程. 好吧,其实也就是上一篇而已啦. 所谓布局,就是指控制窗体容器中各个控件(组件)的位置关 ...

  8. Python基础=== Tkinter Grid布局管理器详解

    本文转自:https://www.cnblogs.com/ruo-li-suo-yi/p/7425307.html          @ 箬笠蓑衣 Grid(网格)布局管理器会将控件放置到一个二维的表 ...

  9. Python Tkinter Grid布局管理器详解

    Grid(网格)布局管理器会将控件放置到一个二维的表格里.主控件被分割成一系列的行和列,表格中的每个单元(cell)都可以放置一个控件. 注意:不要试图在一个主窗口中混合使用pack和grid (1) ...

随机推荐

  1. CSS构造表单

    结构化表单布局 <head> <meta http-equiv="Content-Type" content="text/html; charset=G ...

  2. 使用Aspose.Cells组件生成Excel文件

    生成带表头的Excel文件,格式如下显示. 当然更复杂的一些也可以通过 合并单元格的方法 public void Merge(int firstRow, int firstColumn, int to ...

  3. HDU 1158 Employment Planning【DP】

    题意:给出n个月,雇佣一个人所需的钱hire,一个人工作一个月所需要的钱salary,解雇一个人所需要的钱fire,再给出这n个月每月1至少有num[i]个人完成工作,问完成整个工作所花费的最少的钱是 ...

  4. 编译busybox错误

    为了制作一个文件系统,首先要用busybox编译出文件系统所需要的应用程序.在下载了busybox-1.13.0.tar.bz2后,编译出现如下错误: In file included from /o ...

  5. php数组排序函数

    下边提到的几个数组函数的排序有一些共性: 1 数组被作为排序函数的参数,排序以后,数组本身就发生了改变,函数的返回值为bool类型.2 函数名中出现单a表示association,含义为,在按值排序的 ...

  6. java程序员修炼之道

    今天在论坛里看到了一位工作10年的java大牛总结的java程序员修炼之道,看完后给出的评价是:字字玑珠,深入人心,猛回头,自己一无是处··· 大牛告诉我们应该好好学习与修炼以下知识与技能 Java语 ...

  7. 物联网操作系统HelloX V1.79发布公告

    经过HelloX开发团队近半年的努力,在HelloX V1.78版本基础上,增加许多功能特性,并对V1.78版本的一些特性进行了进一步优化之后,正式形成HelloX V1.79测试版本.经相对充分的测 ...

  8. Heritrix源码分析(四) 各个类说明(转)

    Heritrix的类的确很繁琐,往往继承了一层又一层,最多的继承好像有7层.下面就一个包一个包的说明每个类的作用,由于里面Heritrix组件分明,很多组件没用到的同时该组件的类我也没怎么接触,所以这 ...

  9. UITabbar item 设置笔记

    很长一段时间都是用代码来写UITabbarController,试着用xib来写一次,但是遇到tabbar item的图标自定义的时候不知道从何入手,比如定义选定前和选定后的icon图片,这地方还是不 ...

  10. oracle之检查点(Checkpoint)

    检查点是一个数据库事件,它把修改数据从高速缓存写入磁盘,并更新控制文件和数据文件.检查点分为三类:1)局部检查点:单个实例执行数据库所有数据文件的一个检查点操作,属于此实例的全部脏缓存区写入数据文件. ...