Remove scanned class only when conflicting with imported class

Closes gh-36835
This commit is contained in:
Juergen Hoeller
2026-05-27 16:31:13 +02:00
parent 3e585830d7
commit 121c0ac285
2 changed files with 18 additions and 3 deletions
@@ -260,9 +260,11 @@ class ConfigurationClassParser {
return;
}
else if (configClass.isScanned()) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
if (existingClass.isImported()) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
}
// An implicitly scanned bean definition should not override an explicit import.
return;
@@ -26,6 +26,7 @@ import example.scannable.CustomComponent;
import example.scannable.CustomStereotype;
import example.scannable.DefaultNamedComponent;
import example.scannable.FooService;
import example.scannable.FooServiceImpl;
import example.scannable.MessageBean;
import example.scannable.ScopedProxyTestBean;
import example.scannable_implicitbasepackage.ComponentScanAnnotatedConfigWithImplicitBasePackage;
@@ -43,6 +44,7 @@ import org.springframework.beans.factory.annotation.CustomAutowireConfigurer;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
@@ -84,6 +86,17 @@ class ComponentScanAnnotationIntegrationTests {
assertContextContainsBean(ctx, "fooServiceImpl");
}
@Test
void controlScanWithExplicitRegistration() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.registerBeanDefinition("myFooService", new RootBeanDefinition(FooServiceImpl.class));
ctx.scan(example.scannable.PackageMarker.class.getPackage().getName());
ctx.refresh();
assertContextContainsBean(ctx, "myFooService");
assertContextContainsBean(ctx, "fooServiceImpl");
}
@Test
void viaContextRegistration() {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ComponentScanAnnotatedConfig.class);