手動實現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動態代理結束…
打開異常代碼
沒有成功事務控制成功