Java 的动态代理

Java 的动态代理(Dynamic Proxy)是 Java 提供的一种允许在运行时动态创建代理对象的机制,用于拦截和处理对目标对象方法的调用,它基于 Java 的反射机制,被广泛运用于 AOP (面向切面编程)、框架开发(如 Spring)等领域。

区别于静态代理(需要手动编写代理类),动态代理在运行时通过反射动态生成代理类,无需为每个目标类手动编写代理代码。

Java 中的动态代理主要基于 java.lang.reflect.Proxy 和 InvocationHandler 接口。其中 Proxy 类用于动态生成代理对象,InvocationHandler 接口用于定义代理逻辑,每次调用代理对象的方法时,会触发 InvocationHandler 的 invoke 方法。

动态代理要求目标对象必须实现至少一个接口,因为代理对象是通过接口生成的。

下面给出一个简单的动态代理示例:

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义一个接口
interface UserService {
    void sayHello(String name);
}

// 目标类(被代理的实现类)
class UserServiceImpl implements UserService {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello, " + name + "!");
    }
}

// 自定义 InvocationHandler
class MyInvocationHandler implements InvocationHandler {
    private Object target; // 目标对象

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("方法调用前:记录日志");
        Object result = method.invoke(target, args); // 调用目标对象的方法
        System.out.println("方法调用后:清理资源");
        return result;
    }
}

// 测试
public class Main {
    public static void main(String[] args) {
        // 创建目标对象
        UserServiceImpl target = new UserServiceImpl();

        // 创建 InvocationHandler
        MyInvocationHandler handler = new MyInvocationHandler(target);

        // 生成代理对象
        UserService proxy = (UserService) Proxy.newProxyInstance(
            target.getClass().getClassLoader(), // 类加载器
            target.getClass().getInterfaces(),  // 目标实现的接口
            handler                             // InvocationHandler
        );

        // 调用代理对象的方法
        proxy.sayHello("Alice");
    }
}

输出结果:

java 复制代码
方法调用前:记录日志
Hello, Alice!
方法调用后:清理资源

Prxoy.newProxyInstance 在运行时生成一个代理类,这个代理类的字节码是动态创建的,通常以 $Proxy0 这样的形式命名,代理类的每个方法都会调用 InvocationHandler.invoke 。

当调用代理对象的方法(如 proxy.sayHello)时,实际执行的是 InvocationHandler.invoke。invoke 方法接收三个参数:proxy 表示代理对象本身,method 表示被调用的方法(反射的 Method 对象),args 表示方法参数。在 invoke 中可以自定义逻辑(如日志、权限检查),然后通过 method.invoke(target, args) 调用目标对象的方法。

动态代理实现了代理逻辑与业务逻辑分离,符合 AOP 思想。同一个 InvocationHandler 可以代理多个接口或对象。

动态代理使用的反射机制有一定的性能开销。

相关推荐
代码的余温18 分钟前
5种高效解决Maven依赖冲突的方法
java·maven
慕y27421 分钟前
Java学习第十六部分——JUnit框架
java·开发语言·学习
paishishaba27 分钟前
Maven
java·maven
张人玉1 小时前
C# 常量与变量
java·算法·c#
Java技术小馆1 小时前
GitDiagram如何让你的GitHub项目可视化
java·后端·面试
Codebee1 小时前
“自举开发“范式:OneCode如何用低代码重构自身工具链
java·人工智能·架构
程序无bug2 小时前
手写Spring框架
java·后端
程序无bug2 小时前
Spring 面向切面编程AOP 详细讲解
java·前端
全干engineer2 小时前
Spring Boot 实现主表+明细表 Excel 导出(EasyPOI 实战)
java·spring boot·后端·excel·easypoi·excel导出
Fireworkitte2 小时前
Java 中导出包含多个 Sheet 的 Excel 文件
java·开发语言·excel