在 Java 中,**Proxy(代理)**通常指两种常见场景:
下面从使用方式、最佳实践、常见坑三个角度系统说明。
public interface UserService {
void save();
}
public class UserServiceImpl implements UserService {
public void save() {
System.out.println("save user");
}
}
public class LogProxy implements InvocationHandler {
private Object target;
public LogProxy(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = method.invoke(target, args);
System.out.println("after");
return result;
}
}
// 使用
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new LogProxy(target)
);
✅ 只代理接口,不代理类(JDK Proxy 限制)
✅ InvocationHandler 保持无状态或线程安全
✅ 避免 Proxy 对象被序列化(除非必要)
✅ 不要在 invoke 中再调用 proxy 方法,避免递归
// 错误示例(递归)
public Object invoke(...) {
return method.invoke(proxy, args); // ❌
}
✅ 统一异常处理
try {
return method.invoke(target, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
| 场景 | 代理方式 |
|---|---|
| 有接口 | JDK 动态代理 |
| 无接口 | CGLIB |
@EnableAspectJAutoProxy(proxyTargetClass = true) // 强制 CGLIB
✅ 方法必须是 public(CGLIB 也推荐)
✅ 避免同类方法内部调用(AOP 失效)
public void a() {
b(); // ❌ AOP 不生效
}
@Transactional
public void b() {}
✅ 使用接口而非具体类作为注入类型
@Autowired
UserService userService; // ✅
✅ 事务 / 日志 / 权限统一用 AOP,不要手写 Proxy
典型应用:Feign、MyBatis Mapper、Dubbo
UserService userService = Proxy.newProxyInstance(
classLoader,
new Class[]{UserService.class},
(proxy, method, args) -> rpcInvoke(method, args)
);
✅ 接口只定义契约,不写实现
✅ Proxy 负责网络 / 序列化细节
✅ 方法签名稳定,避免重载
| 场景 | 推荐 |
|---|---|
| 简单日志 / 鉴权 | JDK Proxy |
| Spring 项目 | Spring AOP |
| 高性能字节码 | ByteBuddy |
| Android | 不推荐动态代理 |
⚠️ 动态代理有性能开销,不要在热点循环中创建 Proxy
❌ Proxy 对象 instanceof 实现类 为 false
❌ 私有方法无法被代理
❌ final 类 / final 方法无法 CGLIB
❌ 代理链过深导致调试困难
Java Proxy 的最佳实践:用接口定义行为,用代理处理横切逻辑,避免滥用,优先使用成熟框架(Spring AOP / ByteBuddy)。
如果你有具体使用场景(Spring / RPC / 测试 Mock),我可以给更针对性的示例。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。