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思想,可以橫向地抽取方法中公共類,常用的應用場景有:事務控制、日志紀錄等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM