Skip to content

[ISSUE #12637] Add reference bean naming strategy to avoid @Resource by-name conflicts - #16438

Open
zengbohan1 wants to merge 5 commits into
apache:3.3from
zengbohan1:feat/reference-bean-naming-strategy
Open

[ISSUE #12637] Add reference bean naming strategy to avoid @Resource by-name conflicts#16438
zengbohan1 wants to merge 5 commits into
apache:3.3from
zengbohan1:feat/reference-bean-naming-strategy

Conversation

@zengbohan1

Copy link
Copy Markdown

Problem

When @DubboReference is used on a field, ReferenceAnnotationBeanPostProcessor registers a ReferenceBean whose bean name defaults to the field name (when no explicit id attribute is set). If another bean in the same application context declares a field with the same name but a different type and injects it by name (JSR-250 @Resource), the injection fails.

Reproduction

@RestController
public class Demo2Controller {
    @DubboReference
    private Demo2Service demo1Service;   // registers ReferenceBean 'demo1Service' of type Demo2Service
}

@RestController
public class Demo1Controller {
    @Resource
    private Demo1Service demo1Service;   // by-name lookup hits the Demo2Service proxy -> failure
}

Startup fails with:

Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'demo1Service' is expected to be of type 'com.example.dubbodemo.Demo1Service'
but was actually of type 'com.example.dubbodemo.Demo2ServiceDubboProxy0'

Root cause

This is a cross-annotation conflict with a timing gap:

  1. @DubboReference vs @DubboReference collisions on the same bean name are already handled by a rename fallback (xxx#2) inside registerReferenceBean.
  2. However, @Resource never registers a bean definition; it resolves by name at injection time, which happens after @DubboReference has already registered its ReferenceBean under the field name. So no rename/protection logic can kick in at that point.

Proposal

Add an opt-in naming strategy for reference beans that do not declare an explicit id, selected via a Spring environment property:

dubbo.application.reference-bean-naming-strategy=field-name | interface-name
  • field-name (default, current behavior): bean name = annotated field/setter property name.
  • interface-name (new): bean name = simple name of the referenced service interface, so it no longer depends on the declaring field name.

The default keeps full backward compatibility (non-breaking). An explicit id attribute always takes priority regardless of the strategy.

Verification

Reproduced and verified with a Spring Boot 2.7.13 + Dubbo 3.3.6 + JDK 17 consumer application (ZooKeeper registry) containing exactly the conflicting controllers above, with the patched class applied.

Scenario 1 - default strategy (field-name, property not set): behavior unchanged, still fails

[INFO] Register dubbo reference bean: demo1Service = ReferenceBean:com.example.dubbodemo.Demo2Service()
       at private com.example.dubbodemo.Demo2Service com.example.dubbodemo.Demo2Controller.demo1Service
...
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'demo1Service' is expected to be of type 'com.example.dubbodemo.Demo1Service'
but was actually of type 'com.example.dubbodemo.Demo2ServiceDubboProxy0'

[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0   (mvn test exit code 1)

Scenario 2 - -Ddubbo.application.reference-bean-naming-strategy=interface-name: application starts

[INFO] Register dubbo reference bean: Demo2Service = ReferenceBean:com.example.dubbodemo.Demo2Service()
       at private com.example.dubbodemo.Demo2Service com.example.dubbodemo.Demo2Controller.demo1Service
...
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0           (mvn test exit code 0)

The Demo2Controller reference bean is now registered as Demo2Service; Demo1Controller's @Resource lookup by name finds nothing named demo1Service, falls back to by-type matching and successfully injects the local Demo1ServiceImpl provider bean.

A new test ReferenceBeanNamingStrategyTest covers both strategies (default strategy derives names from the field name including the existing rename-to-#2 fallback; interface-name strategy derives them from the referenced interface simple names).

Note

If desired, maintainers could consider flipping the default value to interface-name in a future major/minor release (e.g. 3.4) after collecting feedback, since it removes a whole class of by-name conflicts.

@codecov-commenter

codecov-commenter commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 69.23077% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.90%. Comparing base (5b7b9c1) to head (2396b8e).
⚠️ Report is 1 commits behind head on 3.3.

Files with missing lines Patch % Lines
...notation/ReferenceAnnotationBeanPostProcessor.java 69.23% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##                3.3   #16438      +/-   ##
============================================
- Coverage     60.94%   60.90%   -0.04%     
- Complexity       30    11767   +11737     
============================================
  Files          1953     1953              
  Lines         89271    89283      +12     
  Branches      13473    13476       +3     
============================================
- Hits          54405    54377      -28     
- Misses        29297    29321      +24     
- Partials       5569     5585      +16     
Flag Coverage Δ
integration-tests-java21 32.09% <38.46%> (-0.06%) ⬇️
integration-tests-java8 32.21% <38.46%> (+<0.01%) ⬆️
samples-tests-java21 32.15% <38.46%> (-0.07%) ⬇️
samples-tests-java8 29.84% <38.46%> (-0.03%) ⬇️
unit-tests-java11 59.15% <69.23%> (-0.07%) ⬇️
unit-tests-java17 58.63% <69.23%> (-0.04%) ⬇️
unit-tests-java21 58.67% <69.23%> (+<0.01%) ⬆️
unit-tests-java25 58.61% <69.23%> (+0.01%) ⬆️
unit-tests-java8 59.16% <69.23%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

2 participants