Preserve existing imported class over scanned configuration class

Closes gh-24643
This commit is contained in:
Juergen Hoeller
2024-02-20 20:43:41 +01:00
parent 266953195c
commit 22b41c33ba
7 changed files with 220 additions and 45 deletions

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation.componentscan.ordered;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author Vladislav Kisel
*/
@Configuration
@Import(SiblingImportingConfigB.class)
public class SiblingImportingConfigA {
@Bean(name = "a-imports-b")
String bean() {
return "valueFromA";
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation.componentscan.ordered;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Vladislav Kisel
*/
@Configuration
public class SiblingImportingConfigB {
@Bean(name = "a-imports-b")
String bean() {
return "valueFromB";
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation.componentscan.ordered;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Vladislav Kisel
*/
@Configuration
public class SiblingReversedImportingConfigA {
@Bean(name = "b-imports-a")
String bean() {
return "valueFromAR";
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation.componentscan.ordered;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @author Vladislav Kisel
*/
@Configuration
@Import(SiblingReversedImportingConfigA.class)
public class SiblingReversedImportingConfigB {
@Bean(name = "b-imports-a")
String bean() {
return "valueFromBR";
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,8 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.componentscan.ordered.SiblingImportingConfigA;
import org.springframework.context.annotation.componentscan.ordered.SiblingImportingConfigB;
import static org.assertj.core.api.Assertions.assertThat;
@@ -362,6 +364,8 @@ class ImportTests {
@Import(A.class)
static class B { }
// ------------------------------------------------------------------------
@Test
void testProcessImports() {
int configClasses = 2;
@@ -369,4 +373,20 @@ class ImportTests {
assertBeanDefinitionCount((configClasses + beansInClasses), ConfigurationWithImportAnnotation.class);
}
/**
* An imported config must override a scanned one, thus bean definitions
* from the imported class is overridden by its importer.
*/
@Test // gh-24643
void importedConfigOverridesScanned() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan(SiblingImportingConfigA.class.getPackage().getName());
ctx.refresh();
assertThat(ctx.getBean("a-imports-b")).isEqualTo("valueFromA");
assertThat(ctx.getBean("b-imports-a")).isEqualTo("valueFromBR");
assertThat(ctx.getBeansOfType(SiblingImportingConfigA.class)).hasSize(1);
assertThat(ctx.getBeansOfType(SiblingImportingConfigB.class)).hasSize(1);
}
}