首页 > 代码库 > Java事务(六) - 使用注解改造

Java事务(六) - 使用注解改造

一. 前言:

在上一篇文章中, 我们讲了使用动态代理完成事务处理, 这种方式将service层的所有public方法都加入事务中, 这显然不是我们需要的,我们需要代理的只是那些需要更改数据库的方法, 在本篇文章中, 我们将使用Java注解来标记需要处理事务的方法.


二. 实例:

1. 代码结构图:



2. 自定义注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional{
}


3. 代理类:

/**
 * 动态代理
 */
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 {
		Method originalMethod = proxy.getClass().getMethod(method.getName(), method.getParameterTypes());
		// 判断方法上是否有Transactional注解
		if (!originalMethod.isAnnotationPresent(Transactional.class)) {
			// 没有注解, 直接调用方法不用控制事务
			return method.invoke(proxy, objects);
		}

		TransactionManager.beginTransaction();
		Object result = null;
		try {
			result = method.invoke(proxy, objects);
			TransactionManager.commit();
		} catch (Exception e) {
			TransactionManager.rollback();
		} finally {
			TransactionManager.close();
		}
		return result;
	}
}

在TransactionInvocationHandle的invoke方法中, 首先判断被代理的方法是否标记有Transactional注解, 

如果没有则直接调用method.invoke(proxy, objects), 否则, 进入事务处理代码.


4. 业务代码类:

/**
 * 业务逻辑层
 */
public class AccountServiceImpl implements AccountService {
	
	@Override
	@Transactional
	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);
	}
}
在方法上标注使用注解.


参考文章:http://www.davenkin.me/post/2013-02-24/40048572306

源码下载: http://download.csdn.net/detail/zdp072/7908913


Java事务(六) - 使用注解改造