[Gen AI] Fix 11758: Ensure @Replaces beans are detected globally #12144
+201
−1
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Issue: #11758
Bug description
The bug occurs because replacement beans (@Replaces) are only discovered among the candidate collection being considered, not across the global registry. As a result, replacements declared elsewhere in the registry (e.g., a non-@context replacement for a @context bean) can be missed, and already-cached singleton instances for the replaced bean can remain in singleton caches, leading to nondeterministic behavior.
Solution / fix
Expand replacement detection in DefaultBeanContext.filterReplacedBeans to scan the global bean registry (beanDefinitionsClasses) for definitions annotated with @Replaces, in addition to any replacement candidates already present. For scanning we prefer checking the BeanDefinitionReference metadata first and only load the full BeanDefinition via the producer if necessary. This will find replacements declared outside the immediate candidate collection.
When we identify that a bean definition is being replaced, invalidate the relevant caches to prevent returning an already-cached / eagerly-instantiated replaced instance. DefaultBeanContext already has purgeCacheForBeanType(Class) which removes candidate caches and cached bean registrations for that type; we call that. In addition, we add a targeted removal API in SingletonScope to remove any singleton registration tied to the replaced BeanDefinitionIdentity so the singleton scope will not return the old instance.
These changes are minimal and targeted: we avoid global cache clears and invalidate only the entries affected by the replaced bean definition.
Steps to reproduce