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

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

相关推荐
purrrew20 分钟前
【Java ee初阶】初始网络
java·网络
程序员Bears24 分钟前
从零打造个人博客静态页面与TodoList应用:前端开发实战指南
java·javascript·css·html5
Helibo4442 分钟前
GESPC++六级复习
java·数据结构·算法
柒七爱吃麻辣烫2 小时前
在Linux中安装JDK并且搭建Java环境
java·linux·开发语言
极小狐2 小时前
极狐GitLab 容器镜像仓库功能介绍
java·前端·数据库·npm·gitlab
努力的搬砖人.2 小时前
如何让rabbitmq保存服务断开重连?保证高可用?
java·分布式·rabbitmq
_星辰大海乀2 小时前
数据库约束
java·数据结构·数据库·sql·链表
多多*2 小时前
Java反射 八股版
java·开发语言·hive·python·sql·log4j·mybatis
码农飞哥3 小时前
互联网大厂Java面试实战:Spring Boot到微服务的技术问答解析
java·数据库·spring boot·缓存·微服务·消息队列·面试技巧
liudongyang1233 小时前
jenkins 启动报错
java·运维·jenkins