Java事务(五) - 使用动态代理

标签: java 代理 | 发表时间:2014-09-13 22:02 | 作者:zdp072
出处:http://blog.csdn.net

一. 前言:

上一篇博文中, 我们使用模板模式进行事务管理, 代码看起来已经很简洁了, 但是还是不太完美, 

我们依然需要在service层编写和事务相关的代码, 即我们需要在service层宗声明一个TransactionTemplate.

本篇文章中, 我们将使用Java提供的动态代理来完成事务处理, 你将看到无论在service层还是在dao层都不会

有事务处理代码


二. 例子:

1. 代码结构图:



2. TransactionProxy

/**
 * 动态代理
 */
public class TransactionProxy {

	public static Object proxyFor(Object object) {
		return Proxy.newProxyInstance(
										object.getClass().getClassLoader(), 
										object.getClass().getInterfaces(), 
										new TransactionInvocationHandler(object)
									 );
	}
}

class TransactionInvocationHandler implements InvocationHandler {
	private Object proxy;

	TransactionInvocationHandler(Object object) {
		this.proxy = object;
	}

	public Object invoke(Object obj, Method method, Object[] objects) throws Throwable {
		TransactionManager.beginTransaction();
		Object result = null;
		try {
			// 调用业务方法
			result = method.invoke(proxy, objects);
			TransactionManager.commit();
		} catch (Exception e) {
			TransactionManager.rollback();
		} finally {
			TransactionManager.close();
		}
		return result;
	}
}
拦截service层的transfer方法, 在调用之前加入事务准备工作, 然后调用原来的transfer方法,

之后根据transfer方法是否执行成功决定commit还是rollback


3. 接口类AccountService

/**
 * 业务逻辑层接口
 */
public interface AccountService{
	public void transfer(Account outAccount, Account inAccount, int money) throws SQLException;
}
使用动态代理, 被代理类和代理类必须要实现相同的接口


4. 业务实现类AccountServiceImpl

/**
 * 业务逻辑层
 */
public class AccountServiceImpl implements AccountService {
	
	@Override
	public void transfer(Account outAccount, Account inAccount, int money) throws SQLException {
		// 查询两个账户
		AccountDAO accountDAO = new AccountDAO();
		outAccount = accountDAO.findAccountById(outAccount.getId());
		inAccount = accountDAO.findAccountById(inAccount.getId());

		// 转账 - 修改原账户金额 
		outAccount.setMoney(outAccount.getMoney() - money);
		inAccount.setMoney(inAccount.getMoney() + money);
		
		// 更新账户金额
		accountDAO.update(outAccount);
		accountDAO.update(inAccount);
	}
}

5. 测试类:

public class TransferTest {
	
	@Test
	public void transferTest() throws SQLException {
		Account out = new Account();
		out.setId(1);
		
		Account in = new Account();
		in.setId(2);
		
		AccountService accountService = new AccountServiceImpl();
		
		// 获取accountService代理
		AccountService accountServiceProxy = (AccountService) TransactionProxy.proxyFor(accountService);
		accountServiceProxy.transfer(out, in, 100);
	}
}
调用proxyFor方法, 传入需要被代理的对象, 返回一个代理对象, 代理对象条用transfer方法会被加入事务处理


三. 总结:

通过动态代理, AccountServiceImpl中所有public方法都被代理了, 即它们都被加入事务中, 这对于service层中所有方法都需要和数据库打交道的情况是可以的, 然而对于service层中不需要和数据库打交道的public方法, 这样做虽然不会报错, 但是却显得多余.





作者:zdp072 发表于2014-9-13 14:02:34 原文链接
阅读:11 评论:0 查看评论

相关 [java 代理] 推荐:

java 动态代理(Proxy)

- - BlogJava_首页
动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实,代理对象对客户隐藏了实际对象. 动态代理可以对请求进行其他的一些处理,在不允许直接访问某些类,. 或需要对访问做一些特殊处理等,这时候可以考虑使用代理. 目前 Java 开发包中提供了对动态代理的支持,但现在只支持对接口的实现. 主要是通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口.

JAVA之JDK动态代理

- - Java - 编程语言 - ITeye博客
在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过这个类和接口,可以生成JDK动态代理类或动态代理对象. Proxy提供了用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类,如果在程序中为一个或多个接口动态的生成实现类,就可以使用Proxy来创建动态代理类,.

Java事务(五) - 使用动态代理

- - CSDN博客推荐文章
在 上一篇博文中, 我们使用模板模式进行事务管理, 代码看起来已经很简洁了, 但是还是不太完美, . 我们依然需要在service层编写和事务相关的代码, 即我们需要在service层宗声明一个TransactionTemplate.. 本篇文章中, 我们将使用Java提供的动态代理来完成事务处理, 你将看到无论在service层还是在dao层都不会.

java 使用动态代理 - ThreadLocal实现事务管理

- - ITeye博客
动态代理:JDK动态代理只能对实现了接口的类进入代理,采用JDK动态代理必须实现InvocationHandler接口,采用Proxy 类创建相应的代理类.. 下面使用Model2(MVC)使用代理事务查询用户基本信息,使用DB2数据库:. 建立表: create table T_USER (. constraint P_KEY_1 primary key (USER_ID) ); 初始化数据: insert into t_user(user_id, user_name, password) values('root', '系统管理员', 'root');.

Zorka 1.0.9 发布,通用 Java 监控代理

- - 开源中国社区最新新闻
Zorka 1.0.9 发布,此版本现已提供 下载,更新内容如下:. Zorka 是个复杂的可编程的分析和监控 Java 运行应用程序的代理工具,无缝集成了流行的监控系统和协议( Zabbix, Nagios, syslog, SNMP),并且提供额外的跟踪,分析功能,以及数据收集器,这些能帮助发现性能问题和一般的系统问题.

[原]Java动态代理的两种实现方法

- -
 AOP的拦截功能是由java中的动态代理来实现的. 说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行. 不同的切入时机对应不同的Interceptor的种类,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等).

《Java事务设计策略》服务器端代理拥有事务的设计模式

- - 酷勤网-挖经验 [expanded by feedex.net]
当您在应用架构中用到命令模式(Command Pattern)或服务器端代理设计模式(Server Delegate Design pattern)时,本章描述的事务设计模式就比较适合了. 在本模式中,服务器端代理组件,作为对服务器的远程接入点,拥有事务并负责对事务实施全面的管理. 其他任何组件,包括客户端组件、领域服务组件、或是持久化组件都不负责管理事务,它们甚至不会察觉到它们正在使用到了事务.

Java中的锁(Locks in Java)

- - 并发编程网 - ifeve.com
原文链接 作者:Jakob Jenkov 译者:申章 校对:丁一. 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂. 因为锁(以及其它更高级的线程同步机制)是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字( 译者注:这说的是Java 5之前的情况).

Java PaaS 对决

- 呆瓜 - IBM developerWorks 中国 : 文档库
本文为 Java 开发人员比较了三种主要的 Platform as a Service (PaaS) 产品:Google App Engine for Java、Amazon Elastic Beanstalk 和 CloudBees RUN@Cloud. 它分析了每种服务独特的技术方法、优点以及缺点,而且还讨论了常见的解决方法.

Java浮点数

- d0ngd0ng - 译言-电脑/网络/数码科技
Thomas Wang, 2000年3月. Java浮点数的定义大体上遵守了二进制浮点运算标准(即IEEE 754标准). IEEE 754标准提供了浮点数无穷,负无穷,负零和非数字(Not a number,简称NaN)的定义. 在Java开发方面,这些东西经常被多数程序员混淆. 在本文中,我们将讨论计算这些特殊的浮点数相关的结果.