zoukankan      html  css  js  c++  java
  • Spring中的Aop(二)--使用aop进行事务控制

    一、Aop的概念,以及改造动机

    我们来看一个场景,在我们的service层,我们需要实现事务控制,所有的操作必须在同一个事务范围内;比如转账方法,A账户转账给B账户,需要提供事务支持;下面我们看一段代码:

    我们可以看到,业务层的事务控制代码,是和我们业务不相关的,可以抽取出来的公共方法,而且又是所有的业务都需要的。
    下面我们开始进行改造;

    二、抽取公共方法到代理类中,让代理帮我们实现事务

    2.1 改造后的原业务方法

       @Override
        public boolean deleteUserAccount(int id) {
            return userAccountDao.deleteUserAccount(id);
        }
    
        @Override
        public void transferMoney(String sourceName, String targetName, float amount) {
            try
            {
                System.out.println("transferMoney 执行了...");
                UserAccount source = userAccountDao.getUserAccountByName(sourceName);
                UserAccount target = userAccountDao.getUserAccountByName(targetName);
                source.setMoney(source.getMoney() - amount);
                target.setMoney(target.getMoney() + amount);
                userAccountDao.updateUserAccount(source);
                userAccountDao.updateUserAccount(target);
            }catch (Exception e){
                throw new RuntimeException(e);
            }
        }
    

    通过上面代码我们可以看到,抽离了事务控制;

    2.2 编写代理类,增强原方法

    package org.study.factory;
    import org.study.service.IUserAccountService;
    import org.study.util.TransactionManager;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class BeanFactory {
        private  IUserAccountService userAccountService;
        private  TransactionManager txManager ;
        public void setUserAccountService(IUserAccountService userAccountService) {
            this.userAccountService = userAccountService;
        }
        public void setTxManager(TransactionManager txManager) {
            this.txManager = txManager;
        }
        /**
         * 对方法进行代理增强,返回
         * @return IUserAccountService
         */
        public IUserAccountService getUserAccountService() {
            IUserAccountService proxyUserAccountService  = (IUserAccountService) Proxy.newProxyInstance(
                    userAccountService.getClass().getClassLoader(),
                    userAccountService.getClass().getInterfaces(),
                    new InvocationHandler() {
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                Object returnVal = null;
                                try {
                                    System.out.println("newProxyInstance 执行了");
                                    txManager.beginTransaction();
                                    returnVal = method.invoke(userAccountService, args);
                                    txManager.commit();
    
                                } catch (Exception ex) {
                                    System.out.println("newProxyInstance 执行了1");
                                    ex.printStackTrace();
                                    txManager.rollback();
                                } finally {
                                    System.out.println("newProxyInstance 执行了2");
                                    txManager.release();
                                }
                                return returnVal;
                        }
                    }
            );
            return proxyUserAccountService;
        }
    }
    

    我们编写了一个代理类,将事务控制放在里面,这样代理类里所有的方法都实现了事务的控制;

    三、验证结果

    3.1 验证事务是否执行

    未执行方法钱的数据

    执行测试代码

        @Test
        public void TestTransfer(){
            proxyUserAccountService.transferMoney("test","test1",200);
        }
    

    查看执行结果:

    我们的转账代码正确地执行了,没有任何异常;

    3.2 在业务方法中抛出异常,验证事务是否控制

    执行测试方法,我们发现抛出了异常

    再去查看数据库的结果:

    证明我们的方法,得到了事务的控制;

    四、总结

    1、对于实现了接口的类,可以使用JDK的Proxy类创建动态代理;未实现接口的类,使用CGLib动态代理;
    2、动态代理是一种Aop思想,可以横向地抽取方法中公共类,常用的应用场景有:事务控制、日志纪录等。

  • 相关阅读:
    Java多线程总结
    Linux命令总结
    Java笔记
    JDK7和JDK8一些重要新特性
    第八周(11.04-11.10)----每周报告
    第八周(11.04-11.10)----结对项目----逆波兰
    第八周(11.04-11.10)----个人作业----历年学生作品点评
    第七周PSP(10.27-11.03)
    第七周(10.27-11.03)----补交第六周(10.20-26)每周例行报告
    个人项目----词频统计WEB(部分功能)
  • 原文地址:https://www.cnblogs.com/zqllove/p/13050558.html
Copyright © 2011-2022 走看看