Spring事务管理的失效和Proxy类型的DataSource
在服务框架中,我们由于需要将DataSource作为第三方服务暴露给其他模块(此处是十分不推荐的,因为如果作为服务那么首先就要求该服务没有状态),因此就采用Jdk的Proxy来实现虚拟DataSource暴露给其他模块以及第三方。
环境:
采用ASF(基于SCA服务框架的应用服务框架)暴露DataSource作为第三方服务,其他模块的Ibatis 的SqlMapClient和Spring的TransactionManager都注入了这个Proxy类型的DataSource。
问题:
发现Spring注入DataSource的Proxy以后,使用是正常的,但是事务却失效了,JDBC事务失效。
分析:
跟踪察看了spring的代码,发现原来spring中的TransactionManager在事务启动和结束的时候,都是首先将DataSource和ConnectionHolder在ThreadLocal中保存,然后在事务过程中获取的都是保存过的Connection,出错也是会滚该Connection。
但是由于当前使用的是Proxy的DataSource,虽然每一次Call的时候都是调用同一个DataSource,但是在事务开始的时候,获取的是注入到TransactionManager中的DataSource Proxy,在事务进行过程中,使用的是新的Proxy,在ThreadLocal中Map中存在了两份DataSource Proxy的信息也就是有两份ConnectionHolder,这导致在事务开始的时候,将connection的autocommit为false,然后放入到第一个DataSource Proxy作为Key的Entry中,无法被后面事务进行所获取,事务进行的时候默认将会通过DataSource产生一个新的Connection同时autocommit失效,因此产生了事务失效的问题。
Spring的事务处理流程图:
<shapetype id="_x0000_t75" stroked="f" filled="f" path=" m@4@5 l@4@11@9@11@9@5 xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0 "></f><f eqn="sum @0 1 0 "></f><f eqn="sum 0 0 @1 "></f><f eqn="prod @2 1 2 "></f><f eqn="prod @3 21600 pixelWidth "></f><f eqn="prod @3 21600 pixelHeight "></f><f eqn="sum @0 0 1 "></f><f eqn="prod @6 1 2 "></f><f eqn="prod @7 21600 pixelWidth "></f><f eqn="sum @8 21600 0 "></f><f eqn="prod @7 21600 pixelHeight "></f><f eqn="sum @10 21600 0 "></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 414.75pt; HEIGHT: 585.75pt" coordsize="21600,21600" type="#_x0000_t75"><imagedata o:title="" src="E13197E4.files/image001.emz"></imagedata></shape>
图 1 Spring 事务处理流程图
解决方法:
其实只需要让Spring 的TransactionManager能够将DataSource真实实例获得并作为Entry Key保存到ThreadLocal中即可,那么就有两种方式,一种将就是将分开的配置放在一起,那么这里看TransactionManager应该是外部不需要配置的,可以和DataSource配置在一个spring中,那么就不需要用Proxy的方式,另一种不得不用Proxy的方式,例如对于Ibatis的SqlMapClient。处理方法如下:
<shape id="_x0000_i1026" style="WIDTH: 415.5pt; HEIGHT: 288.75pt" coordsize="21600,21600" type="#_x0000_t75"><imagedata o:title="" src="E13197E4.files/image003.emz"></imagedata></shape>
图 2 DataSource 解决方法类图
不再将DataSource作为服务暴露给第三方,而是将内部封装DataSource的IDataSourceHandler来作为服务暴露,同时调用方通过工厂类直接将IDataSourceHandler服务注入,就可以达到在调用方这边获取到的是DataSource的实例,但是需要注意的就是,由于ASF服务框架是动态随机加载各个组件,可能在服务被调用的时候尚未发布,因此需要在注入的时候设置为lazy-init为true。
结论:
Proxy被运用约来广泛,但是也会造成一些再运用Proxy代理的实例作为框架业务逻辑的情况,必须弄清楚情况然后选择如何调用和组装,同时作为服务暴露给第三方,尽量选择无状态的接口服务。
分享到:
相关推荐
Spring框架提供了多种事务管理方式,其中包括编程式事务管理和声明式事务管理。在这个例子中,我们将聚焦于Spring的声明式事务管理,特别是通过`TransactionProxyFactoryBean`代理机制以及`@Transactional`注解与AOP...
《Spring事务管理详解》 在Java企业级应用开发中,数据一致性是至关重要的,而Spring框架的事务管理机制就是为了解决这个问题。本教程将深入探讨Spring中的事务管理,包括其核心概念、配置方式以及实战应用。 首先...
Spring AOP通过代理模式为我们提供了在运行时向目标对象添加拦截器或切面的能力,这在进行日志记录、性能监控、事务管理等场景下非常实用。 首先,让我们了解代理模式的基本概念。代理模式是一种设计模式,它为一个...
Spring 事务管理是其核心特性之一,用于确保在执行数据库操作时的一致性和可靠性。它提供了五种不同的配置方式来适应不同的应用场景。以下是对这些配置方式的详细解释: 1. **基于代理的事务管理(Proxy-based ...
在Spring的AOP模块中,动态代理是一个重要的概念,它允许我们在不修改原有代码的情况下,为方法添加额外的功能,如日志记录、性能监控、事务管理等。本篇将深入探讨Spring中的JDK动态代理。 首先,让我们理解什么是...
在本课程中,我们将深入探讨Spring事务传播原理和数据库事务操作的基本概念,这对于有Spring开发经验的人员来说,是进一步深化事务控制理解的关键。我们还将触及分布式事务的初步知识,帮助开发者更好地掌握基于...
在本示例中,"Spring示例_Printer_Spring_AOP_Spring_Proxy" 主要关注的是Spring框架中的核心概念,特别是AOP(面向切面编程)和代理模式的应用。让我们深入探讨这些知识点。 首先,Spring框架是Java开发中最常用的...
这使得我们可以在不修改原始代码的情况下,为方法添加日志、事务管理、性能监控等功能。 总的来说,Spring AOP通过组合Advice、Pointcut和Advisor,以及使用`ProxyFactoryBean`生成的代理对象,实现了面向切面的...
以下是对Spring事务配置五种方式的详细解释: 1. **基于代理的事务管理(Proxy-based Transaction Management)** 这是第一种配置方式,每个Bean都有一个独立的代理。在示例代码中,`TransactionProxyFactoryBean`...
用于分布式跟踪的库(如果在classpath中找到)可启用jdbc连接和查询跟踪(仅适用于p6spy或datasource-proxy) 为什么不将DataSource包装在配置中? 除了使用库之外,您还可以手动包装DataSource ,但是该库还提供了...
本文将深入探讨如何使用Spring的IOC和DI特性,结合动态代理(Dynamic Proxy)来实现一种类似AOP(面向切面编程)的功能,以达到在不修改原有代码的情况下增强或拦截方法调用的目的。 **一、Spring IOC(控制反转)*...
1. **Spring 事务处理**:Spring 提供了声明式事务管理,允许开发者在配置文件中定义事务边界,无需在业务逻辑代码中显式控制事务开始、提交和回滚。它主要基于AOP代理来实现,通过TransactionInterceptor拦截器进行...
在Spring框架中,事务管理是核心特性之一,它确保了数据操作的一致性和完整性。Spring3引入了基于注解的事务管理,极大地简化了事务配置,使得开发者可以在方法级别声明事务边界,这就是`@Transactional`注解的用处...
在Spring框架中,事务管理是...解决这类问题需要从各个角度排查,确保每个环节都符合Spring事务管理的要求。对于具体的代码问题,建议参考官方文档、相关教程和社区讨论,如给出的博客链接,来获取更详细的解答和示例。
本文将详细介绍Spring事务管理配置的五种方式,帮助你更好地理解和掌握这一关键概念。 首先,Spring事务管理通常涉及三个主要部分: 1. **DataSource**:这是数据库连接的来源,负责提供与数据库交互的资源。例如...
特别地,DataSourceTransactionManager是Spring提供的事务管理器,它利用DataSource进行事务的开始、提交、回滚操作。 再来看FactoryBean模式。FactoryBean是Spring框架中的一种特殊bean,它不是实际的对象实例,...
在Spring中,AOP主要用于实现日志记录、事务管理、性能监控等跨切面关注点。 “proxy”则指的是代理,在Spring AOP中,主要有两种代理方式:JDK动态代理和CGLIB代理。JDK动态代理是基于接口的,当目标对象实现了...