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. poj 2192 (DP)

    这个题题目意思是给你三个字符串str1,str2,str3.将str3从左自右扫描,去匹配str1和str2中的元素,不可重复,若存在一种匹配方法使得str1和str2都被匹配完全了,则输出yes,否 ...

  2. 51nod1204 Parity

    如果sm[j]和sm[i]奇偶性相同,那么(i+1,j)个数为偶数如果奇偶性相同看成是朋友,不同的看成是敌人,那么就跟bzoj1370的做法差不多了. 如果奇偶性相同,就将x和y合并,x+n,y+n合 ...

  3. C实现类封装、继承、多态

    1.  概述 C语言是一种面向过程的程序设计语言,而C++是在C语言基础上衍生来了的面向对象的语言,实际上,很多C++实现的底层是用C语言实现的,如在Visual C++中的Interface其实就是 ...

  4. sql的 group by 分组;linq的 group by 分组

    先来看看 linq的,下面的一段linq 是 ,在 学生导入数据的时候,我们根据学生的手机号码和学生名称进行分组,如果有重复的,我们就筛选出来,用到了 linq的 group by,注意这里是new出 ...

  5. 重装yum

    1)卸载yum rpm -aq|grep yum|xargs rpm -e --nodeps 2)下载并安装python-urlgrabber,python-pycurl,yum-metadata-p ...

  6. hadoop NameNode 实现分析

    在hadoop 整体分析中,说过nameNode主要是实现一个 blockID 到对应 dataNode的对应关系映射. 现在分析一下腰实现这个映射,nameNode还需要哪些模块. 1 为了方便用户 ...

  7. 【英语】Bingo口语笔记(50) - Drop系列

  8. Centos移除图形界面

    在此之前为了试验SAS Linux,在一台centos服务器上安装了desktop界面, 目前需要删除这些界面组件,可以按照以下步骤实现: 1. yum grouplist查看安装的组件 2. 使用y ...

  9. openlayers加载地图没有图片时有红叉的解决方法

    解决方式:设置样式隐藏图片 <style type="text/css"> .olImageLoadError { /*ol2.12 onImageLoadError ...

  10. Java正确转换html编码

    Java 中能將 html 編碼正確轉換的套件: org.apache.commons.lang.StringEscapeUtils. String source = "The less t ...