Skip to content

fix(core): 隔离 Spring Bean 名称,避免被前缀注解和相邻组件污染 - #344

Merged
1lck merged 3 commits into
1lck:previewfrom
Rangsh:fix/315-spring-bean-name-isolation
Aug 30, 2026
Merged

fix(core): 隔离 Spring Bean 名称,避免被前缀注解和相邻组件污染#344
1lck merged 3 commits into
1lck:previewfrom
Rangsh:fix/315-spring-bean-name-isolation

Conversation

@Rangsh

@Rangsh Rangsh commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #315

Spring 索引在检测阶段已经用注解边界确认 @Bean 和组件注解,但命名阶段仍保留两条宽松路径:

  • bean_names 使用 find("@Bean"),会把 @BeanFactory("decoy") 误当成 @Bean,返回 decoy
  • component_name 用宽范围正则跨注解捕获,可能得到 ) @Component(

本 PR 将命名逻辑与检测阶段对齐:只从准确匹配的注解该注解自己的参数范围里提取名称;多个组件注解并存时,按源码位置最靠前的注解取值。

Changes

  • bean_names:改用 SpringAnnotation::Bean.pattern().find() + isolate_annotation_at,替换 find("@Bean")
  • component_name:拆分“定位”和“参数解析”,新增 earliest_component_annotation_start,按 Match::start() 选最靠前的组件注解
  • 修正 COMPONENTS 注释:数组顺序不决定胜者,只保证检测与命名支持范围一致
  • 新增单元测试与 spring.index 集成测试,覆盖 issue 中的复现场景

Test plan

  • @BeanFactory("decoy") @Bean("real") 只返回 real
  • 单独的 @BeanFactory("decoy") 不生成 Bean
  • @Service("s") @Component("c") 返回 s,不产生跨注解字符串
  • @Component("c") @Service("s") 返回 c(验证不依赖 COMPONENTS 数组顺序)
  • 六种组件注解各自的单注解命名测试继续通过
  • 无参数 @Bean 继续走默认 Bean 名称
  • cargo test --manifest-path rust/Cargo.toml -p lithe-core
  • scripts/verify-rust-core-comments.sh
  • cargo fmt --check

Notes

检测阶段已用注解边界确认 Bean,命名却仍用朴素前缀搜索,会从 BeanFactory 读到 decoy。
组件名称的宽捕获也会跨过右括号读到相邻注解。现在只从源码最靠前的准确注解参数里取值。

Co-authored-by: Cursor <cursoragent@cursor.com>
@Rangsh
Rangsh requested a review from 1lck as a code owner August 30, 2026 02:02
@Rangsh
Rangsh changed the base branch from main to preview August 30, 2026 02:04
@Rangsh

Rangsh commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

@lithe review

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Lithe Review

结论: ⛔ 存在阻塞问题
依据: Issue #315 · eab95a5f13f997c597061d4eed7477d2599bf370 ← 656a55f0b0f470945767a169e4dfd4a5cdbc353c · head: 656a55f0

变更理解

本 PR 将 Bean/组件名称解析改为先定位精确注解,再通过 isolate_annotation_at 截取参数范围,并按源码位置选择组件注解。

发现

  1. [P1] 注解隔离器未忽略字符串中的括号,仍可能把相邻注解纳入 Bean 别名
    rust/lithe-core/src/languages/spring.rs:1609-1622

    isolate_annotation_at 对参数文本中的每个 ( / ) 都直接调整 depth,没有跟踪 Java 字符串及转义状态。合法输入 @Bean("foo(") @Bean("bar") 中,字符串里的 ( 会使深度无法在第一个注解的真实右括号处归零,函数最终返回剩余整段文本;bean_names 随后会解析出 ["foo(", "bar"]。这会把相邻注解的值错误登记为 Bean 别名,导致按 bar 的注入/查找错误命中该 Bean,并可能产生重复或错误的 Bean 关系。应在括号扫描时跳过字符串(并处理转义),只对注解语法中的括号计数;同时补充包含字符串括号和相邻注解的回归测试。

验证

  • 已检查限定 diff、bean_index 调用链、annotation_context、共享注解模式及 Spring 单元/集成测试。
  • PR 提供的 CI:Plugin CI gate、Plugin tests and package verification、Rust database tests、Classify changes 已成功;Release package verification、Swift tests、Rust Core and Swift bridge tests、Windows implementation、Swift database tests 仍为 in_progress
  • 本次审查未运行测试。

isolate_annotation_at 把字符串里的括号也计入深度,遇到 @bean("foo(") 会吞掉相邻注解。
括号扫描现在跟踪引号和转义,只对注解语法中的括号计数。

Co-authored-by: Cursor <cursoragent@cursor.com>
@Rangsh

Rangsh commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

@lithe review

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

Lithe Review

结论: ✅ 未发现明确问题
依据: Issue #315 · eab95a5f13f997c597061d4eed7477d2599bf370 ← 65a8ea0af4e1ea39e41efd1f0bd8b2a637815527 · head: 65a8ea0a

LGTM

验证

  • 已检查限定 diff、Spring Bean/组件命名调用链及相关单元和集成测试。
  • PR 提供的 Plugin CI gate、Database CI gate 已成功;Windows 实现检查仍为进行中。
  • 本次审查未运行测试。

@1lck 1lck left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

发现 1 个阻塞的正确性回归:空的组件注解值会被当作实际 Bean 名称,导致合法的 @component("") 不再回退到默认类名。其余改动与 #315 的目标一致,现有 Rust Core 校验均通过。

.and_then(|capture| capture.get(2))
.map(|value| value.as_str().to_string())
let start = earliest_component_annotation_start(context)?;
quoted_values(isolate_annotation_at(context, start))

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

这里改用 quoted_values(...).next() 后,会接受空字符串,因为 quoted_values 的捕获组使用了 *。因此 @Component("") 返回 Some(""),bean_index 中的 unwrap_or(default_name) 不会执行,最终生成空 Bean 名和异常 ID。旧实现的捕获组使用 +,该场景会返回 None 并回退到类名。请过滤空值(或使用组件专用的非空提取逻辑),并补充 @Component("") 的单元与 spring.index 集成测试。

quoted_values 会接受空字符串,@component("") 变成 Some("") 后不再走类名回退。
现在忽略空捕获,与旧的非空捕获行为一致,避免空名称和异常 ID。

Co-authored-by: Cursor <cursoragent@cursor.com>

@1lck 1lck left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

补充两条非阻塞的代码质量建议:1) 新增集成测试目前主要使用 contains / !contains,建议对完整 Bean 集合或至少数量与关键字段做更精确断言,避免遗漏未被显式排除的额外错误项;2) 删除重复的 assert_ne!,前面的 assert_eq!(..., Some("s")) 已经覆盖同一回归场景。

Comment thread rust/lithe-core/src/tests/spring.rs
Comment thread rust/lithe-core/src/languages/spring.rs
@1lck
1lck merged commit 2ade6d4 into 1lck:preview Aug 30, 2026
13 checks passed
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.

[Bug] Spring Bean 名称解析会被前缀注解和相邻组件注解污染

2 participants