手动实现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动态代理结束…
打开异常代码
没有成功事务控制成功