proxy 与 reflect 是设计绑定的协作机制:proxy 负责拦截操作,reflect 负责执行标准化默认行为,二者共同保障代理语义正确性、receiver 绑定准确性和行为可预测性。

Proxy 和 Reflect 是一对紧密配合的机制,不是可选搭配,而是设计上就绑定的协作关系。Proxy 负责“拦截”,Reflect 负责“执行默认行为”,二者共同构成完整、安全、可预测的元编程链条。
Proxy 拦截操作,但不负责实现默认逻辑
Proxy 的 handler 中定义的 trap(如 get、set)只负责“在操作发生时介入”,它本身不提供标准的对象访问或赋值能力。如果你在 get 里直接写 target[prop],看似可行,实则绕过了代理上下文的关键保障:
- 丢失 receiver 绑定:getter/setter 中的
this可能指向错误对象(比如继承链中本该是 proxy,却变成 target) - 无法处理 Symbol 属性或原型链上的访问细节
- 静默失败风险:例如
target[prop] = value在某些 descriptor 下可能不生效,却不报错
Reflect 提供与 trap 一一对应的标准化方法
Reflect 的每个静态方法(如 Reflect.get、Reflect.set、Reflect.has 等)都严格对应一个 trap,参数签名完全一致,且保证:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 返回明确结果(
Reflect.set返回布尔值表示是否成功) - 自动传递 receiver,确保 getter/setter 中的
this正确指向代理对象 - 行为与 JavaScript 引擎内部操作对齐,不会跳过代理层
协作才是真正的“代理语义”
一个符合规范的 Proxy handler,其核心逻辑通常是“先自定义,再委托”:
- 需要日志?在
get里打印,然后调用Reflect.get(target, prop, receiver) - 需要只读?在
set里判断属性名,拒绝修改,并返回false;否则调用Reflect.set(...) - 需要响应式触发?在
set后调用依赖收集函数,再交由Reflect.set完成赋值
这种模式让拦截逻辑清晰、可维护,也避免因手动操作 target 导致代理失效或行为不一致。
不配合 Reflect 的 Proxy 容易出问题
单独用 target[prop] 或 delete target[prop] 看似省事,但在以下场景会暴露缺陷:
- 目标对象有 getter:直接访问
target[prop]会让this指向 target,而非当前 proxy - 代理被继承:子类通过
super.prop访问时,receiver是子类实例,必须由Reflect.get正确转发 - 使用
Object.defineProperty设置了 accessor descriptor:手动赋值会跳过 setter,而Reflect.set会正确触发
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










