Skip to content

工厂模式 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);
    }
}

基于 VitePress 构建 | 技术知识库