Skip to content

[Feature] 允许扩展 ReflectLoader#loadField 支持自定义字段取值处理器 - #443

Open
Ayasaz wants to merge 3 commits into
alibaba:mainfrom
Ayasaz:feature/extend-field-handler
Open

[Feature] 允许扩展 ReflectLoader#loadField 支持自定义字段取值处理器#443
Ayasaz wants to merge 3 commits into
alibaba:mainfrom
Ayasaz:feature/extend-field-handler

Conversation

@Ayasaz

@Ayasaz Ayasaz commented Jun 8, 2026

Copy link
Copy Markdown

背景

当前 QLExpress4 的 ReflectLoader#loadField 对非标准容器(如 Flink Row、Spark Row、JDBC ResultSet、自定义 MapLike/CollectionLike)的字段取值是封闭的,用户无法在 QL 表达式 obj.col_a 中直接使用这些结构,必须先做 convert copy。

改动

仿照已有的 ExtensionFunction + addExtendFunction 扩展模式,新增一个轻量 ExtendFieldHandler 接口,作为 loadField 可插拔的自定义字段取值处理链。

  • 新增 ExtendFieldHandler (@FunctionalInterface)—— 支持 lambda 注册,返回 null 表示不匹配
  • ReflectLoader 添加 addExtendFieldHandler + CopyOnWriteArrayList<ExtendFieldHandler> 处理链
  • loadField 方法在最前面插入扩展分支:遍历 handler,返回非 null 则消费,全部返回 null 则走原有逻辑
  • Express4Runner 透传 addExtendFieldHandler
  • 新增 ExtendFieldHandlerTest 4 个测试用例(匹配、不匹配穿透、回退、多链)

兼容性

不影响现有行为。不注入 FieldHandler 时与原分支逻辑完全一致。全量测试 208 跑通(2 个 Error 是基线已有的 map/filter 环境问题,与本次修改无关)。

文件变更

文件 改动
ExtendFieldHandler.java 新增(+40 行)
ReflectLoader.java 修改(+30 行)
Express4Runner.java 修改(+13 行)
ExtendFieldHandlerTest.java 新增(+109 行)

Closes #415

新增 ExtendFieldHandler (@FunctionalInterface) 接口,允许用户在 ReflectLoader
中注册自定义的字段取值逻辑,支持对非标准容器(如 Flink Row、JDBC ResultSet、
自定义 MapLike/CollectionLike 等)进行属性访问。

改动:
- 新增 ExtendFieldHandler (FunctionalInterface) 到 function 包
- ReflectLoader 添加 addExtendFieldHandler + fieldHandlers 处理链
- loadField 在最前面插入扩展分支,handler 返回 null 则继续下一个
- Express4Runner 透传 addExtendFieldHandler

不影响现有行为,不注入 FieldHandler 时与原来完全一致。

Closes alibaba#415
@CLAassistant

CLAassistant commented Jun 8, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@DQinYuan

Copy link
Copy Markdown
Collaborator

注释可以改成英文吗?

Comment thread src/main/java/com/alibaba/qlexpress4/runtime/ReflectLoader.java Outdated
…glish doc

Per review feedback on alibaba#443:
- Bind ExtendFieldHandler to a receiver Class<?> (mirroring
  addExtendFunction(String, Class<?>, QLFunctionalVarargs)) so registrations
  cannot conflict and dispatch is by isAssignableFrom.
- Handler now returns a raw Object instead of the low-level Value; ReflectLoader
  wraps it into DataValue, so users no longer touch internal runtime structures.
- Rewrite all comments/Javadoc in English.
- Update tests accordingly (4 cases, incl. super-type binding).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread src/main/java/com/alibaba/qlexpress4/runtime/ReflectLoader.java Outdated
Comment thread src/main/java/com/alibaba/qlexpress4/runtime/ReflectLoader.java Outdated

@DQinYuan DQinYuan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

另外,在README-source.adoc和README-EN-source.adoc分别补一下这个功能的中英文文档

…null semantics & docs

Per review feedback on alibaba#443 (commit 2cab1c1):
- Store ExtendFieldHandler registrations in a CopyOnWriteArrayList (mirroring
  extensionFunctions) instead of a ConcurrentHashMap, matching the read-heavy /
  write-rare access pattern and keeping registration order deterministic.
- A matched handler (bean assignable to its binding class) is now authoritative:
  its return value including null is taken as the field value, so a field that is
  present but null no longer falls through to reflection and gets reported as
  missing. The default logic only applies when no binding class matches.
- Document the feature in README-source.adoc / README-EN-source.adoc and the
  generated README.adoc / README-EN.adoc.
- Update ExtendFieldHandlerTest accordingly (null-value authority, handler wins
  over reflection) and add a doc example tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Ayasaz

Ayasaz commented Jul 6, 2026

Copy link
Copy Markdown
Author

@DQinYuan 已按 review 全部更新(commit b37cf2c):

  1. fieldHandlers 改为 CopyOnWriteArrayList(配一个绑定 class+handler 的 Holder),与上面的 extensionFunctions 一致;
  2. 「字段不存在 vs 值为 null」改用「匹配即权威」语义消解:类型绑定了 handler 即视为该类型的权威取值来源,返回 null 表示字段值就是 null,不再穿透反射;只有没有任何 bindingClass 匹配时才走默认逻辑(详见对应行的回复);
  3. 已在 README-source.adoc / README-EN-source.adoc(及生成的 README.adoc / README-EN.adoc)补充「扩展字段取值 / Extend Field Handler」中英文文档;
  4. ExtendFieldHandlerTest 相应更新并新增权威性用例,6 个用例全绿;全量测试无新增失败(map/filter 两个 Error 是基线已有的环境问题)。

麻烦再看下,谢谢!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

考虑允许拓展ReflectLoader#loadField?

3 participants