Java动态代理模式详解:原理与MyBatis实战解析

苏见山
苏见山
发布时间:2026-10-14| 5人浏览过
原创

代理模式作为Java设计中不可或缺的一环,主要分为静态代理与动态代理。其中动态代理利用JVM反射机制在运行时生成字节码,实现了业务逻辑与通用功能的解耦,也是MyBatis等主流框架的核心技术基础。

一、 动态代理原理概述

动态代理(Dynamic Proxy)是在程序运行期间,运用反射机制动态创建代理类的实例。与需要预先编写代码并编译的静态代理不同,动态代理类在内存中瞬时生成,具有更高的灵活性。

JDK标准库提供了java.lang.reflect.Proxy类用于处理动态代理,其核心入口为newProxyInstance()方法。该方法接收类加载器、接口数组以及一个实现InvocationHandler接口的调用处理器,最终返回一个符合指定接口的代理对象。

第1步:定义业务接口与实现类

为了演示代理流程,首先需要构建一个基础的DAO层结构。这代表了系统中实际的“委托对象”,即真正执行业务逻辑的组件。

目标接口 Dao.java

package javaproxy;
public interface Dao {
    // 模拟数据保存操作
    void save();
}

目标实现类 DaoImpl.java

package javaproxy;
public class DaoImpl implements Dao {
    @Override
    public void save() {
        System.out.println("执行一个保存方法。。。。。。。。。。。。");
    }
}

第2步:实现 InvocationHandler 调用处理器

动态代理的关键在于控制代理对象的行为。通过实现InvocationHandler接口,我们可以捕获所有对代理对象的函数调用,并在转发给真实对象前后插入附加逻辑(如日志、权限校验等),这是AOP实现的基石。

调用处理器 DaoHandler.java

package javaproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DaoHandler implements InvocationHandler {
    private Object obj;

    public DaoHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("do something before method"); // 前置增强
        // 使用反射调用真实目标对象的方法
        Object ret = method.invoke(this.obj, args);
        System.out.println("do something after method"); // 后置增强
        return ret;
    }
}

第3步:创建代理对象并测试

客户端不再直接获取DaoImpl实例,而是通过Proxy.newProxyInstance将目标对象包装成代理。此后对代理对象的方法调用,都会被路由到DaoHandler的invoke方法中。

客户端调用 Client.java

package javaproxy;
import java.lang.reflect.Proxy;

public class Client {
    public static void main(String[] args) {
        // 1. 元对象(被代理的真实对象)
        DaoImpl daoImpl = new DaoImpl();

        // 2. 绑定调用处理器
        DaoHandler daoHandler = new DaoHandler(daoImpl);

        // 3. 创建代理实例
        // 参数说明:ClassLoader、接口数组、InvocationHandler
        Dao dao = (Dao) Proxy.newProxyInstance(
                daoImpl.getClass().getClassLoader(),
                daoImpl.getClass().getInterfaces(),
                daoHandler
        );

        // 4. 触发代理行为
        dao.save();
    }
}

执行上述代码后,控制台会依次打印前置处理信息、业务方法内容以及后置处理信息,验证了动态拦截的成功。运行结果示意如下:

二、 模拟 MyBatis Mapper 代理机制

在实际应用中,动态代理常被用于解决重复样板代码的问题。MyBatis 就是典型代表:它并不存在具体的 DAO 实现类,而是通过在 XML/注解中定义 SQL 映射,然后在运行时动态生成 Mapper 接口的代理对象。

第4步:通用 Mapper 代理工具类

我们将创建一个通用的代理工厂MapperProxy。它可以接受任意接口和上下文(如SqlSession),并生成对应的代理。这里重点演示如何通过泛型让工具类适配任何接口。

Mapper 代理工厂 MapperProxy.java

package javaproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MapperProxy implements InvocationHandler {

    /**
     * 获取代理对象的静态方法
     * @param mapperInterface 接口类
     * @param sqlSession      会话上下文(此处简化为null)
     * @return 生成的代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T newMapperProxy(Class<T> mapperInterface, Object sqlSession) {
        ClassLoader classLoader = mapperInterface.getClassLoader();
        // 代理必须实现指定的接口
        Class[] interfaces = new Class[] { mapperInterface };
        
        MapperProxy handler = new MapperProxy();
        return (T) Proxy.newProxyInstance(classLoader, interfaces, handler);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // 在实际MyBatis中,此处会根据method.getName()查找对应的SQL语句并执行
        System.out.println("在此处通过反射解析并执行实际SQL方法");
        return null;
    }
}

第5步:调用无具体实现类的接口

此时客户端可以直接调用MapperProxy生成的代理。即使没有写DaoImpl的具体代码,调用依然能触发invoke中的自定义逻辑。

客户端调用 Client2.java

package javaproxy;

public class Client {
    public static void main(String[] args) {
        // 利用工厂方法直接获取Dao接口的代理对象
        Dao dao = MapperProxy.newMapperProxy(Dao.class, null);
        
        // 调用代理方法
        dao.save();
    }
}

同样地,该流程也能成功执行并进入拦截逻辑:

三、 总结

通过对比可见,JDK动态代理极大地降低了代码耦合度。它使得我们在不修改原有业务代码的前提下,通过代理切面统一处理横切关注点(Cross-cutting Concerns)。掌握这一模式,是深入阅读 Spring AOP、RPC 框架以及 MyBatis 等中间件源码的前提。

以上就是 Java 动态代理模式的详细内容,更多关于 Java 设计模式与框架底层原理的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。