手動實現IOC與事務控制-基於JDBC-2-動態代理改造Service事務

手動實現IOC與事務控制-基於JDBC
https://blog.csdn.net/ko0491/article/details/106939211
之前實現了,IOC與事務,但是在Service中有很大一段try-catch代理,事務代碼與業務代碼混合在一起
在這裏插入圖片描述

使用動態代理改造Service

對所有的Service使用動態代理
在這裏插入圖片描述
思路:
在Servlet中不再直接調用ServiceImpl,而是調用了使用動態代理增加了事務控制後的代理對象

  • 創建動態代理工廠

package com.liu.spring.proxy.transaction;

import com.liu.spring.transaction.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Description 事務代理工廠
 * @ClassName TransactionProxyFactory
 * @Author 劉楠
 * @date 2020.06.24
 */
public class TransactionProxyFactory {

    private TransactionProxyFactory(){

    }
    private static  TransactionProxyFactory transactionProxyFactory = new TransactionProxyFactory();

    public static  TransactionProxyFactory getInstance(){

        return transactionProxyFactory;

    }

    public Object getJdkProxy(Object obj){

        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("開始使用jdk動態代理...");
                        Object result=null;
                        try {

                            TransactionManager.getInstance().beginTransaction();
                             result = method.invoke(obj, args);
                            TransactionManager.getInstance().commitTransaction();
                        }catch (Exception e){
                            e.printStackTrace();
                            //使用事務管理器回滾事務
                            TransactionManager.getInstance().rollbackTransaction();
                            //拋出異常 便於上層 捕獲
                            throw  new RuntimeException(e);
                        }
                        System.out.println("使用jdk動態代理結束...");
                        return result;

                    }
                });
    }

    public Object getCglibProxy(Object object){

        return Enhancer.create(object.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object proxyObject, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                System.out.println("開始使用cgLib動態代理...");
                Object result=null;
                try {

                    TransactionManager.getInstance().beginTransaction();
                    result = method.invoke(object, args);
                    TransactionManager.getInstance().commitTransaction();
                }catch (Exception e){
                    e.printStackTrace();
                    //使用事務管理器回滾事務
                    TransactionManager.getInstance().rollbackTransaction();
                    //拋出異常 便於上層 捕獲
                    throw  new RuntimeException(e);
                }
                System.out.println("使用cgLib動態代理結果...");
                return result;
            }
        });
    }


}

改造service 去掉事務控制代碼


package com.liu.spring.service.impl;

import com.liu.spring.dao.AccountDao;
import com.liu.spring.dao.impl.AccountDaoImpl;
import com.liu.spring.entity.Account;
import com.liu.spring.factory.BeanFactory;
import com.liu.spring.service.TransferService;
import com.liu.spring.transaction.TransactionManager;
import com.liu.spring.util.ConnectionUtils;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * @Description
 * @ClassName TransferServcieImpl
 * @Author 劉楠
 * @date 2020.06.23
 */
public class TransferServcieImpl implements TransferService {

//   private AccountDao accountDao = new AccountDaoImpl();

    private AccountDao accountDao ;




    @Override
    public boolean transfer(String fromAccount, String toAccount, Integer money) throws Exception {
        System.out.println("=====開始轉賬==== ");



        try {
            /**
             * 開啓事務關閉事務的自動提交
             */
//            ConnectionUtils.getInstance().getCurrentConnection().setAutoCommit(false);
            //使用事務管理器-開啓使用
            //TransactionManager.getInstance().beginTransaction();
            Account fAccount = accountDao.queryByCardNo(fromAccount);
            Account tAccount = accountDao.queryByCardNo(toAccount);

            fAccount.setMoney(fAccount.getMoney()-money);
            tAccount.setMoney(tAccount.getMoney()+money);
            accountDao.updateAccountByCardno(fAccount);
//            int i=1/0;
            accountDao.updateAccountByCardno(tAccount);
            /**
             * 正常執行完成 提交事務
             */
//            ConnectionUtils.getInstance().getCurrentConnection().commit();
            //使用事務管理器-提交事務
            //TransactionManager.getInstance().commitTransaction();
        }catch (Exception e){
            e.printStackTrace();
            /**
             * 有異常回滾事務
             */
//            ConnectionUtils.getInstance().getCurrentConnection().rollback();
            //使用事務管理器回滾事務
            //TransactionManager.getInstance().rollbackTransaction();
            //拋出異常 便於上層 捕獲
            throw  new RuntimeException(e);
        }

        return true;
    }

    /**
     * 提供get,set方法
     * @return
     */
    public AccountDao getAccountDao() {
        return accountDao;
    }

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
}

改造Servelt

@WebServlet(name = "transferServlet",urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {
    /**
     * http mine,json類型
     */
    public static final String MIME_TYPE_JSON = "application/json";
    /**
     * http mine,json類型指定utf-8編碼
     */
    public final static String MIME_TYPE_JSON_UTF8 = MIME_TYPE_JSON + ";charset=UTF-8";
    //1.實例化TransferService
//    private TransferService transferService = new TransferServcieImpl();
//    private TransferService transferService =(TransferService) BeanFactory.getBean("transferService");
    //從代理工廠獲取增加了事務功能的對象
    private TransferService transferService=(TransferService) TransactionProxyFactory.getInstance()
                                .getJdkProxy(BeanFactory.getBean("transferService"));
....
}

測試正常

在這裏插入圖片描述

發起測試
在這裏插入圖片描述
在這裏插入圖片描述

開始使用jdk動態代理…
=開始轉賬
queryByCardNo connection com.mysql.jdbc.JDBC4Connection@7c60e05f
queryByCardNo connection com.mysql.jdbc.JDBC4Connection@7c60e05f
updateAccountByCardno connection com.mysql.jdbc.JDBC4Connection@7c60e05f
updateAccountByCardno connection com.mysql.jdbc.JDBC4Connection@7c60e05f
使用jdk動態代理結束…

打開異常代碼

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
沒有成功事務控制成功
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章