JAVA:动态代理机制及应用的技术指南

admin
1
2026-01-26

1、简述

Java 动态代理(Dynamic Proxy)是 Java 反射体系的重要能力之一,它能够在运行时动态生成代理类,从而无需在编译期就定义代理逻辑。动态代理广泛应用于 AOP(Aspect-Oriented Programming)、RPC 框架、ORM 框架、监控埋点、权限控制等领域。

本文将从原理、实现方式、关键特性以及实际应用角度系统介绍 Java 动态代理,并提供可直接运行的实践示例代码。

image-iibx.png


2、什么是动态代理?

代理模式允许开发者为目标对象提供一个“代理”,由该代理来控制对目标对象的访问。与静态代理相比,动态代理无需手动编写代理类,而是由 JVM 在运行时生成。

Java 提供了两种主流的动态代理方式:

🔥 JDK 动态代理(基于接口) 依赖 java.lang.reflect.ProxyInvocationHandler,要求目标类必须实现接口。

🔥 CGLIB 动态代理(基于继承)
通过生成子类字节码来完成代理,无需接口,但不能代理 final 类或 final 方法。

JDK 动态代理原理解析

JDK 动态代理基于以下两个核心组件:

InvocationHandler

一个回调接口,用于接管代理对象对目标方法的执行。

public interface InvocationHandler {
    Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

Proxy

用于动态生成代理类字节码。


3、JDK 动态代理实践用例

以下示例展示了如何使用 Java 自带的动态代理机制为业务接口添加日志功能。

3.1 定义业务接口与实现类

public interface OrderService {
    void createOrder(String userId, String productId);
}

public class OrderServiceImpl implements OrderService {
    @Override
    public void createOrder(String userId, String productId) {
        System.out.println("正在创建订单:userId = " + userId + ", productId = " + productId);
    }
}

3.2 编写动态代理(日志增强)

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

public class LoggingInvocationHandler implements InvocationHandler {

    private final Object target;

    public LoggingInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("[LOG] 调用方法:" + method.getName());
        if (args != null) {
            for (Object arg : args) {
                System.out.println("[LOG] 参数:" + arg);
            }
        }
        Object result = method.invoke(target, args);
        System.out.println("[LOG] 方法执行完成:" + method.getName());
        return result;
    }
}

3.3 创建代理对象

import java.lang.reflect.Proxy;

public class DynamicProxyDemo {
    public static void main(String[] args) {
        OrderService orderService = new OrderServiceImpl();

        OrderService proxy = (OrderService) Proxy.newProxyInstance(
                orderService.getClass().getClassLoader(),
                orderService.getClass().getInterfaces(),
                new LoggingInvocationHandler(orderService)
        );

        proxy.createOrder("U1001", "P2002");
    }
}

3.4 输出效果

[LOG] 调用方法:createOrder
[LOG] 参数:U1001
[LOG] 参数:P2002
正在创建订单:userId = U1001, productId = P2002
[LOG] 方法执行完成:createOrder

4、CGLIB 动态代理实践示例

当业务类没有实现接口时,可以使用 CGLIB(如 Spring AOP 内部使用)。

Maven 依赖(如未由 Spring 自动提供)

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

示例代码

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibLoggingProxy implements MethodInterceptor {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("[CGLIB LOG] 调用:" + method.getName());
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("[CGLIB LOG] 执行完成:" + method.getName());
        return result;
    }

    public static <T> T createProxy(Class<T> clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(new CglibLoggingProxy());
        return (T) enhancer.create();
    }
}

public class PayService {
    public void pay(int amount) {
        System.out.println("支付金额:" + amount);
    }
}

public class CglibDemo {
    public static void main(String[] args) {
        PayService proxy = CglibLoggingProxy.createProxy(PayService.class);
        proxy.pay(300);
    }
}

5、总结

动态代理是 Java 中极为重要的底层机制,具有以下优势:

🔥 无需手写代理类,减少重复代码

🔥 增强逻辑可集中处理,符合 AOP 设计思想

🔥 适用于多种框架和中间件的底层实现

理解动态代理,不仅能帮助我们更好地理解 Spring、MyBatis 等框架,也能在实际业务开发中灵活实现日志、监控、权限等横切功能。

动态代理常见应用场景:

领域 说明
AOP(面向切面编程) 日志、缓存、事务、性能分析等切面逻辑
RPC 框架 如 Dubbo:通过代理调用远程服务
ORM 框架 MyBatis Mapper 动态代理执行 SQL
Spring 事务管理 利用代理在方法前后加入事务切面
监控 & 埋点系统 收集接口调用信息

如果你正在构建一个可扩展的系统,动态代理机制绝对值得深入掌握。

动物装饰