温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java Proxy 代理如何工作

发布时间:2026-08-31 22:53:57 来源:亿速云 阅读:94 作者:小樊 栏目:编程语言

在 Java 中,Proxy(代理)通常指 JDK 动态代理(Dynamic Proxy),它是 Java 反射机制的一部分,用于在运行时动态生成代理类,从而在不修改原始类代码的情况下增强或控制方法调用。

下面从 概念 → 原理 → 使用 → 底层机制 → 局限 几个方面说明。


一、Proxy 代理解决什么问题?

假设你有一个接口:

public interface UserService {
    void save();
}

实现类:

public class UserServiceImpl implements UserService {
    public void save() {
        System.out.println("保存用户");
    }
}

如果你希望在不改 UserServiceImpl 的情况下:

  • 打印日志
  • 做事务
  • 做权限校验

就可以用 Proxy 代理。


二、JDK 动态代理的核心类

1️⃣ java.lang.reflect.Proxy

  • 用于创建代理对象
  • 核心方法:
Proxy.newProxyInstance(
    ClassLoader loader,
    Class<?>[] interfaces,
    InvocationHandler h
);

2️⃣ java.lang.reflect.InvocationHandler

  • 代理对象的方法调用都会走到这里
public interface InvocationHandler {
    Object invoke(Object proxy, Method method, Object[] args);
}

三、Proxy 代理使用示例

1️⃣ 定义 InvocationHandler

public class LogHandler implements InvocationHandler {

    private Object target;

    public LogHandler(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;
    }
}

2️⃣ 创建代理对象

UserService userService = new UserServiceImpl();

UserService proxy = (UserService) Proxy.newProxyInstance(
        userService.getClass().getClassLoader(),
        userService.getClass().getInterfaces(),
        new LogHandler(userService)
);

proxy.save();

输出:

方法前:日志
保存用户
方法后:日志

四、Proxy 是如何工作的?(原理)

✅ 1. 只能代理「接口」

Proxy.newProxyInstance(
    loader,
    interfaces,  // 必须是接口
    handler
);

❌ 不能代理普通类
✅ 只能代理接口


✅ 2. 运行时动态生成代理类

JDK 在运行时生成一个类似这样的类(简化):

class $Proxy0 implements UserService {
    private InvocationHandler h;

    public void save() {
        h.invoke(this, saveMethod, null);
    }
}
  • 代理类名称通常为:$Proxy0, $Proxy1
  • 所有接口方法都转发给 InvocationHandler.invoke

✅ 3. 方法调用流程

proxy.save()
   ↓
InvocationHandler.invoke()
   ↓
method.invoke(target, args)

五、Proxy 底层实现简要说明

  1. 字节码生成

    • 使用 sun.misc.ProxyGenerator
    • 在内存中生成 .class 字节码
  2. 类加载

    • 使用传入的 ClassLoader 加载代理类
  3. 缓存

    • 相同接口 + ClassLoader 的代理类会被缓存

六、Proxy 代理的局限性

❌ 只能代理接口
❌ 性能略低于直接调用
✅ 适合 AOP、RPC、事务、日志等场景


七、与 CGLIB 的对比

特性 JDK Proxy CGLIB
代理目标 接口 类
原理 反射 + 接口 继承 + 字节码
Spring 默认 有接口时用 无接口时用

八、典型使用场景

  • Spring AOP
  • RPC 框架(远程调用)
  • 事务管理
  • 权限校验
  • 日志 / 监控

如果你愿意,我也可以:

  • 画一张 Proxy 调用流程图
  • 结合 Spring AOP 讲
  • 对比 JDK Proxy vs CGLIB 源码

你想从哪方面继续深入?

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手