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. HDU 2059 龟兔赛跑

    受上一道题影响,我本来想着开一个二维数组来表示充电和不充电的状态. 可这样就有一个问题,如果没有充电,那么在下一个阶段就有剩余的电量. 这样问题貌似就不可解了,难道是因为不满足动态规划的无后效性这一条 ...

  2. 比较满意设计的一次作业 JDBC宠物管理

    package com.dao; import java.util.List; import com.entity.Master; public interface MasterDao { publi ...

  3. 解决Eclipse快捷键被其他软件占用

    做为一个java攻城狮,eclipse是我最常用的攻城设备,eclipse快捷键 极大的提高了我的开发效率!!!! 前段时间升级了一下我的战斗装备——给电脑的系统盘换成了一个固态硬盘,因此需要重装系统 ...

  4. php 获取301 302的真实地址

    function getRealURL($url){ $header = get_headers($url,1); if (strpos($header[0],'301') || strpos($he ...

  5. 在Android中使用并发来提高速度和性能

    Android框架提供了很实用的异步处理类.然而它们中的大多数在一个单一的后台线程中排队.当你需要多个线程时你是怎么做的? 众所周知,UI更新发生在UI线程(也称为主线程).在主线程中的任何操作都会阻 ...

  6. 学好Javascript是有方法的

    先声明下噢,这篇文章不是自个儿写的,看着好,希望前端小孩们可以和我一起加油,大家都来借鉴借鉴吧- 首先要说明的是,咱现在不是高手,最多还是一个半桶水,算是入了JS的门. 谈不上经验,都是一些教训. 这 ...

  7. Bootstrap初级用户谈谈网页在手机上的显示效果优化

    本人之前已经使用Bootstrap有一段时间了,但是之前做出的网站都只是在电脑端使用,没有注意过手机端的显示效果.这两天自己使用Bootstrap做了一个简单的Web个人日志系统,想在手机端也使用,桌 ...

  8. 【原创】Linux下编译链接中常见问题总结

    前言 一直以来对Linux下编译链接产生的问题没有好好重视起来,出现问题就度娘一下,很多时候的确是在搜索帮助下解决了BUG,但由于对原因不求甚解,没有细细研究,结果总是在遇到在BUG时弄得手忙脚乱得. ...

  9. 【leetcode】Find Minimum in Rotated Sorted Array II JAVA实现

    一.题目描述 Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed ...

  10. 12、NFC技术:读写NFC标签中的Uri数据

    功能实现,如下代码所示: 读写NFC标签的Uri 主Activity import cn.read.write.uri.library.UriRecord; import android.app.Ac ...