spring的annotation-driven配置事务管理器详解

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

时间: 2024-10-15 13:06:31

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

spring 配置事务管理器

在Spring中数据库事务是通过PlatformTransactionManager进行管理的,jdbcTemplate是不能支持事务的,而能够支持事务的是org.springframework.transaction.support.TransactionTemplate模板,它是Spring所提供的事务管理器的模板 •事务的创建.提交和回滚是通过PlatformTransactionManager接口来完成的. •当事务产生异常时会回滚事务,在默认的实现中所有的异常都会回滚.我们可以通过配置

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

写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都

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

文章转自:http://blog.csdn.net/trigl/article/details/50968079 写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 一.初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱.  比如你去ATM机取1000块钱,

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

Spring4.X + spring MVC + Mybatis3 零配置应用开发框架搭建详解(1) - 基本介绍 spring集成 mybatis Spring4.x零配置框架搭建 两年前一直在做后台的纯Java开发,很少涉及web开发这块,最近换了个纯的互联网公司,需要做Web后台管理系统,之前都是用xml配置的项目,接触了公司Spring4.x的零配置项目,觉得非常有感觉,不仅仅配置简单,而且条理清晰,所以,这里把学习的内容记录下来,一来加深对这块技术的印象,另外准备做个简单的教程,如果给

rpm程序包管理器详解

1. 程序包管理器的功能 我们知道,由程序员编写并提供的程序源代码要转换成目标二进制格式才能在计算机上运行起来,但用户要在平台上使用时需要手动编译安装后才能使用,对于普通用户来说有一定难度.因此为了降低普通用户对应用程序的使用难度,程序员可在提供源代码的同时提供已在特定环境下编译好的程序文件,只要用户的平台环境和程序员的平台环境相同,就可以通过解压程序员提供的二进制格式文件即可使用,而无需自己手动编译安装. 一个已编译好的程序由二进制程序.库文件.配置文件和帮助手册等组成,而程序包管理器的功能就

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

本文转自:https://www.cnblogs.com/ruo-li-suo-yi/p/7425307.html          @ 箬笠蓑衣 Grid(网格)布局管理器会将控件放置到一个二维的表格里.主控件被分割成一系列的行和列,表格中的每个单元(cell)都可以放置一个控件. 注意:不要试图在一个主窗口中混合使用pack和grid (1)标签控件 1 from tkinter import * 2 3 tk=Tk() 4 #标签控件,显示文本和位图,展示在第一行 5 Label(tk,t

Spring整合mybatis时使用事务管理器

异常报告:java.lang.AbstractMethodError: org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout()Ljava/lang/Integer; 可以尝试更换更高版本的mybatis-spring.xxx.jar包 原文地址:https://www.cnblogs.com/SysoCjs/p/9460514.html

NLB网路负载均衡管理器详解

序言 在上一篇配置iis负载均衡中我们使用啦微软的ARR,我在那篇文章也中提到了网站的高可用性,但是ARR只能做请求入口的消息分发服务,这样如果我们的消息分发服务器给down掉啦,那么做再多的应用服务集群也都枉然. 这篇文章我主要针对解决这一问题来做分析,引入NLB,相对于ARR来说,ARR算是应用级别的负载均衡方案,而NLB则是服务器级别的负载均衡方案. 如果微软的这两款方案我们结合起来使用,那便是微软高可用网站方案的天作之合啦. Application Request Route与NLB高可

spring整合mybatis以及配置事务

提前说明: 整合目的:使mybatis支持事务代理 需要做的工作: 1.将mybatis对象的创建交由spring ①配置第三方带有连接池的数据源 ②spring创建sqlsession对象 ③mybatis通过映射接口创建对象,spring不支持通过接口创建对象,需要给出解决方案(在整合包) 2.配置事务 ①配置事务管理器 ②配置通知 ③使用AOP切入 具体步骤: 1.配置数据源 <!-- 配置数据源 --> <bean name="dataSource" clas