码迷,mamicode.com
首页 > 编程语言 > 详细

Spring中的Aop(二)

时间:2020-06-05 16:51:33      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:name   数据   str   override   try   util   验证   getc   方法   

一、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思想,可以横向地抽取方法中公共类,常用的应用场景有:事务控制、日志纪录等。

Spring中的Aop(二)

标签:name   数据   str   override   try   util   验证   getc   方法   

原文地址:https://www.cnblogs.com/zqllove/p/13050558.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!