赞
踩
在现代企业级应用开发中,事务管理是一项关键的技术,它可以保证一系列操作要么全部成功,要么全部失败,从而确保数据的一致性和完整性。Spring框架提供了强大的事务管理能力,但有时为了更细粒度地控制事务边界,我们可能需要自己实现事务管理逻辑。本文将介绍如何结合Spring框架和JDK动态代理技术来实现一个简单的事务管理系统。
在本示例中,我们将创建一个基于Spring框架的应用程序,该程序包含一个账户服务接口(IAccountService
),以及其实现类(AccountServiceImp
)。为了增强该服务的事务处理能力,我们将创建一个工厂类(ProxyBeanFactory
),它会为IAccountService
生成一个动态代理对象,该对象能够在调用真实服务方法前后自动开启和提交事务。
首先,我们需要配置Spring的bean定义。下面是一个简化版的Spring配置文件示例:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 数据源配置略 --> <!-- QueryRunner配置略 --> <!-- 连接工具类配置略 --> <!-- 事务工具类配置略 --> <!-- 数据访问层配置略 --> <!-- 业务逻辑层配置略 --> <bean id="proxyService" class="org.example.service.IAccountService" factory-bean="factory" factory-method="createProxy"></bean> <bean id="factory" class="org.example.factory.ProxyBeanFactory"> <property name="transactionUtil" ref="transactionUtil"></property> <property name="toProxyService" ref="service"/> </bean> <!-- 控制器配置略 --> </beans>
如上所示,ProxyBeanFactory
将创建一个实现了IAccountService
接口的代理对象,并且会在执行业务逻辑之前和之后自动管理事务。
接下来,我们来看一下ProxyBeanFactory
类的具体实现:
package org.example.factory; import org.example.service.IAccountService; import org.example.util.TransactionUtil; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyBeanFactory { private IAccountService toProxyService; private TransactionUtil transactionUtil; public void setToProxyService(IAccountService toProxyService) { this.toProxyService = toProxyService; } public void setTransactionUtil(TransactionUtil transactionUtil) { this.transactionUtil = transactionUtil; } public IAccountService createProxy() { return (IAccountService) Proxy.newProxyInstance( toProxyService.getClass().getClassLoader(), toProxyService.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; try { transactionUtil.beginTx(); result = method.invoke(toProxyService, args); transactionUtil.commitTx(); } catch (Exception e) { transactionUtil.rollbackTx(); } finally { transactionUtil.closeTx(); } return result; } } ); } }
ProxyBeanFactory
类的核心在于createProxy
方法,它使用JDK动态代理机制来创建代理对象。当任何IAccountService
接口方法被调用时,都会触发InvocationHandler
中的invoke
方法,从而开启事务、执行业务逻辑并最终提交或回滚事务。
示例代码:
applicationContext.xml:
<!-- 加载资源文件 --> <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder> <!-- 注入数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${msg1}"/> <property name="jdbcUrl" value="${msg2}"/> <property name="user" value="${msg3}"/> <property name="password" value="${msg4}"/> </bean> <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner"> <constructor-arg name="ds" ref="dataSource"/> </bean> <!-- 连接工具类 --> <bean id="connectionUtil" class="org.example.util.ConnectionUtil"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 事务工具类 --> <bean id="transactionUtil" class="org.example.util.TransactionUtil"> <property name="connectionUtil" ref="connectionUtil"/> </bean> <bean id="mapperImp" class="org.example.dao.AccountMapperImp"> <property name="queryRunner" ref="queryRunner"></property> <property name="connectionUtil" ref="connectionUtil"></property> </bean> <bean id="service" class="org.example.service.AccountServiceImp"> <property name="dao" ref="mapperImp"></property> </bean> <bean id="proxyService" class="org.example.service.IAccountService" factory-bean="factory" factory-method="createProxy"></bean> <bean id="factory" class="org.example.factory.ProxyBeanFactory"> <property name="transactionUtil" ref="transactionUtil"></property> <property name="toProxyService" ref="service"/> </bean> <bean id="controller" class="org.example.controller.AccountControllerImp"> <property name="service" ref="proxyService"></property> </bean> </beans>
ProxyBeanFactory:
public class ProxyBeanFactory { IAccountService toProxyService;; //装配事务工具类 TransactionUtil transactionUtil; public void setAccountServiceImp(IAccountService accountServiceImp) { toProxyService = accountServiceImp; } public void setToProxyService(IAccountService toProxyService) { this.toProxyService = toProxyService; } public void setTransactionUtil(TransactionUtil transactionUtil) { this.transactionUtil = transactionUtil; } public IAccountService getAccountServiceImp() { return toProxyService; } //2.创建代理 public IAccountService createProxy(){ IAccountService proxy = (IAccountService) Proxy.newProxyInstance(toProxyService.getClass().getClassLoader(), toProxyService.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = null; try { transactionUtil.beginTx(); obj = method.invoke(toProxyService, args); transactionUtil.commitTx(); } catch (Exception e) { e.printStackTrace(); transactionUtil.rollbackTx(); } finally { transactionUtil.closeTx(); } return obj; } }); return proxy; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。