Appearance
工厂模式 BasicFactory 与 JDK 动态代理事务管理
本文探讨基于反射与配置文件的 BasicFactory 对象工厂解耦方案,以及如何使用 JDK 动态代理为 Service 业务层无侵入式地织入全局事务控制。
1. 工厂模式 BasicFactory 解耦
在未引入 Spring IOC 框架前,如果 Controller 直接通过 new UserServiceImpl() 实例化 Service, Service 与具体的实现类构成了强耦合。一旦更换实现类,需要修改大量的调用代码。
使用 BasicFactory + 配置文件,实现解耦:
配置文件 beans.properties
properties
net.wanho.service.UserServiceI=net.wanho.service.impl.UserServiceImpl
net.wanho.dao.UserDaoI=net.wanho.dao.impl.UserDaoImpl工厂类实现 BasicFactory.java
java
public class BasicFactory {
private static Properties props = new Properties();
static {
try {
InputStream in = BasicFactory.class.getClassLoader()
.getResourceAsStream("beans.properties");
props.load(in);
} catch (IOException e) {
throw new ExceptionInInitializerError("加载 beans.properties 失败");
}
}
@SuppressWarnings("unchecked")
public static <T> T getBean(Class<T> interfaceClass) {
try {
String className = props.getProperty(interfaceClass.getName());
Class<?> clazz = Class.forName(className);
return (T) clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException("创建 Bean 失败: " + interfaceClass.getName(), e);
}
}
}2. JDK 动态代理声明式事务控制
在包含转账或多表更新的业务中,事务控制应该作用在 Service 业务层(保证原子性)。但如果让 Service 的每个方法都手写连接与 conn.setAutoCommit(false),会导致代码极度臃肿。
通过 JDK 动态代理 (InvocationHandler),可以自动对目标 Service 进行代理包装,实现声明式事务切面织入:
动态代理处理器 TransactionProxy.java
java
package net.wanho.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import net.wanho.transaction.TransManagerI;
public class TransactionProxy implements InvocationHandler {
private Object target; // 被代理的目标 Service 实现类对象
private TransManagerI transManager; // 事务管理器
@SuppressWarnings("unchecked")
public static <T> T getProxy(T target, TransManagerI transManager) {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new TransactionProxy(target, transManager)
);
}
private TransactionProxy(Object target, TransManagerI transManager) {
this.target = target;
this.transManager = transManager;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
// 1. 自动开启全局事务 (setAutoCommit(false))
transManager.beginTransaction();
// 2. 执行目标 Service 方法的核心业务代码
result = method.invoke(target, args);
// 3. 业务执行成功,自动提交事务
transManager.commit();
} catch (Exception e) {
// 4. 捕获任何业务异常,自动回滚事务!
transManager.rollback();
throw e.getCause(); // 抛出真实原始异常
} finally {
// 5. 关闭并释放数据库连接
transManager.close();
}
return result;
}
}3. 架构解耦整合效果
使用工厂模式与代理后,Web 层的调用体验非常简洁且完全脱离了底层事务代码:
java
@WebServlet("/transfer")
public class TransferServlet extends HttpServlet {
// 1. 通过工厂获取业务接口实例
private UserServiceI userServiceRaw = BasicFactory.getBean(UserServiceI.class);
// 2. 为业务接口穿上动态代理事务外衣
private UserServiceI userService = TransactionProxy.getProxy(userServiceRaw, new TransManagerImpl());
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
// 调用业务代码,事务自动在背后生效!
userService.transferMoney("Alice", "Bob", 500.0);
}
}