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 可以代理多个接口或对象。

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

相关推荐
星辰烈龙23 分钟前
黑马程序员Java基础9
java·开发语言
山沐与山24 分钟前
【Redis】Redis集群模式架构详解
java·redis·架构
ss27334 分钟前
Java并发编程:DelayQueue延迟订单系统
java·python·算法
wcy_101139 分钟前
七大软件设计原则
java·设计规范
invicinble40 分钟前
jar包在执行的时候需要关注的细节(提供一个解构jvm问题的视角)
java·jvm·jar
麦芽糖021942 分钟前
SSE介绍及使用(Server-Send Events)
java
alan07211 小时前
【Java + Elasticsearch全量 & 增量同步实战】
java·elasticsearch·jenkins
hashiqimiya1 小时前
后端springboot的接收前端发来的数据反序列化原理
java
cat三三2 小时前
java之异常
java·开发语言
浙江第二深情2 小时前
前端性能优化终极指南
java·maven