在 Java 中,Proxy(代理)通常指 JDK 动态代理(Dynamic Proxy),它是 Java 反射机制的一部分,用于在运行时动态生成代理类,从而在不修改原始类代码的情况下增强或控制方法调用。
下面从 概念 → 原理 → 使用 → 底层机制 → 局限 几个方面说明。
假设你有一个接口:
public interface UserService {
void save();
}
实现类:
public class UserServiceImpl implements UserService {
public void save() {
System.out.println("保存用户");
}
}
如果你希望在不改 UserServiceImpl 的情况下:
就可以用 Proxy 代理。
java.lang.reflect.ProxyProxy.newProxyInstance(
ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h
);
java.lang.reflect.InvocationHandlerpublic interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args);
}
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;
}
}
UserService userService = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
new LogHandler(userService)
);
proxy.save();
输出:
方法前:日志
保存用户
方法后:日志
Proxy.newProxyInstance(
loader,
interfaces, // 必须是接口
handler
);
❌ 不能代理普通类
✅ 只能代理接口
JDK 在运行时生成一个类似这样的类(简化):
class $Proxy0 implements UserService {
private InvocationHandler h;
public void save() {
h.invoke(this, saveMethod, null);
}
}
$Proxy0, $Proxy1InvocationHandler.invokeproxy.save()
↓
InvocationHandler.invoke()
↓
method.invoke(target, args)
字节码生成
sun.misc.ProxyGenerator.class 字节码类加载
ClassLoader 加载代理类缓存
❌ 只能代理接口
❌ 性能略低于直接调用
✅ 适合 AOP、RPC、事务、日志等场景
| 特性 | JDK Proxy | CGLIB |
|---|---|---|
| 代理目标 | 接口 | 类 |
| 原理 | 反射 + 接口 | 继承 + 字节码 |
| Spring 默认 | 有接口时用 | 无接口时用 |
如果你愿意,我也可以:
你想从哪方面继续深入?
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。