【Java高级工程师蜕变之路】009 手写IOC和AOP
传统开发方式的问题分析
new关键字耦合问题解决
new关键字耦合问题代码实现
beans.xml定义
<?xml version="1.0" encoding="utf-8" ?>
TransferServlet使用
private TransferService transferService = (TransferService) BeanFactory.getBean("transferService");
TransferServiceImpl定义
// 最佳状态
private AccountDao accountDao;
// 构造函数传值/set方法传值
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
核心的BeanFactory实现
public class BeanFactory {
/**
* 任务一:读取并解析xml,通过反射实例化对象并存储,用map结构存储
* 任务二:对外提供根据ID获取对象的接口
*/
private static Map map = new HashMap<>();
static {
// 任务一:读取并解析xml,通过反射实例化对象并存储,用map结构存储
// 加载xml
InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
// 解析xml
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(resourceAsStream);
Element rootElement = document.getRootElement();
List beanList = rootElement.selectNodes("//bean");
for (int i = 0; i < beanList.size(); i++) {
Element element = beanList.get(i);
// 通过bean元素,获取id和class
String id = element.attributeValue("id");
String clazz = element.attributeValue("class");
// 通过反射实例化对象
Class<?> aClass = Class.forName(clazz);
Object o = aClass.newInstance();
map.put(id, o);
}
// 维护对象的依赖关系
// 找到有property子元素的bean
List propertyList = rootElement.selectNodes("//property");
for (int j = 0; j < propertyList.size(); j++) {
Element element = propertyList.get(j);
String name = element.attributeValue("name");
String ref = element.attributeValue("ref");
// 找到有property的bean
Element parent = element.getParent();
// 父元素反射赋值
String parentId = parent.attributeValue("id");
Object parentObject = map.get(parentId);
Method[] methods = parentObject.getClass().getMethods();
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
if (method.getName().equals("set" + name)) {
method.invoke(parentObject, map.get(ref));
}
}
// 重新赋值
map.put(parentId, parentObject);
}
} catch (DocumentException | ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 任务二:对外提供根据ID获取对象的接口
*
* @param id
* @return
*/
public static Object getBean(String id) {
return map.get(id);
}
}
Service层未添加事务解决
问题分析:
数据库事务是Connection的事务
connection.commit();//提交事务
Connection.rollback();//回滚事务
解决思路:
1)两次update使用同一个conenction链接
两次update属于同一个线程的执行调用,从同一个线程中拿到
2)把事务控制在service层
代码实现
/*try{
// 开启事务(关闭事务的自动提交)
TransactionManager.getInstance().beginTransaction();*/
Account from = accountDao.queryAccountByCardNo(fromCardNo);
Account to = accountDao.queryAccountByCardNo(toCardNo);
from.setMoney(from.getMoney()-money);
to.setMoney(to.getMoney()+money);
accountDao.updateAccountByCardNo(to);
// int c = 1/0;
accountDao.updateAccountByCardNo(from);
/* // 提交事务
TransactionManager.getInstance().commit();
}catch (Exception e) {
e.printStackTrace();
// 回滚事务
TransactionManager.getInstance().rollback();
// 抛出异常便于上层servlet捕获
throw e;
}*/
动态代理改造Service
定义代理工厂类
/**
* @author: terwer
* @date: 2021/12/14 22:58
* @description: 代理对象工厂,主要用于生产对象
*/
public class ProxyFactory {
private TransactionManager transactionManager;
public void setTransactionManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* Jdk动态代理
* @param obj 委托对象
* @return 代理对象
*/
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 {
Object result = null;
try{
// 开启事务(关闭事务的自动提交)
transactionManager.beginTransaction();
result = method.invoke(obj,args);
// 提交事务
transactionManager.commit();
}catch (Exception e) {
e.printStackTrace();
// 回滚事务
transactionManager.rollback();
// 抛出异常便于上层servlet捕获
throw e;
}
return result;
}
});
}
/**
* 使用cglib动态代理生成代理对象
* @param obj 委托对象
* @return
*/
public Object getCglibProxy(Object obj) {
return Enhancer.create(obj.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = null;
try{
// 开启事务(关闭事务的自动提交)
transactionManager.beginTransaction();
result = method.invoke(obj,objects);
// 提交事务
transactionManager.commit();
}catch (Exception e) {
e.printStackTrace();
// 回滚事务
transactionManager.rollback();
// 抛出异常便于上层servlet捕获
throw e;
}
return result;
}
});
}
}
代码
https://github.com/terwer/transfer-test