Merge branch '3.1.x'

Closes gh-38507
This commit is contained in:
Phillip Webb 2023-11-22 11:13:12 -08:00
commit 9f031b04e5
2 changed files with 71 additions and 2 deletions

View File

@ -36,6 +36,7 @@ import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Style;
import org.springframework.context.annotation.Bean;
@ -279,7 +280,7 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
private Set<String> collectBeanNamesForAnnotation(ListableBeanFactory beanFactory,
Class<? extends Annotation> annotationType, boolean considerHierarchy, Set<String> result) {
result = addAll(result, beanFactory.getBeanNamesForAnnotation(annotationType));
result = addAll(result, getBeanNamesForAnnotation(beanFactory, annotationType));
if (considerHierarchy) {
BeanFactory parent = ((HierarchicalBeanFactory) beanFactory).getParentBeanFactory();
if (parent instanceof ListableBeanFactory listableBeanFactory) {
@ -289,6 +290,30 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
return result;
}
private String[] getBeanNamesForAnnotation(ListableBeanFactory beanFactory,
Class<? extends Annotation> annotationType) {
Set<String> foundBeanNames = new LinkedHashSet<>();
for (String beanName : beanFactory.getBeanDefinitionNames()) {
if (beanFactory instanceof ConfigurableListableBeanFactory configurableListableBeanFactory) {
BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(beanName);
if (beanDefinition != null && beanDefinition.isAbstract()) {
continue;
}
}
if (beanFactory.findAnnotationOnBean(beanName, annotationType, false) != null) {
foundBeanNames.add(beanName);
}
}
if (beanFactory instanceof SingletonBeanRegistry singletonBeanRegistry) {
for (String beanName : singletonBeanRegistry.getSingletonNames()) {
if (beanFactory.findAnnotationOnBean(beanName, annotationType) != null) {
foundBeanNames.add(beanName);
}
}
}
return foundBeanNames.toArray(String[]::new);
}
private boolean containsBean(ConfigurableListableBeanFactory beanFactory, String beanName,
boolean considerHierarchy) {
if (considerHierarchy) {

View File

@ -28,11 +28,13 @@ import java.util.function.Consumer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport.ConditionAndOutcomes;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -131,6 +133,19 @@ class ConditionalOnBeanTests {
});
}
@Test
void beanProducedByFactoryBeanIsConsideredWhenMatchingOnAnnotation2() {
this.contextRunner
.withUserConfiguration(EarlyInitializationFactoryBeanConfiguration.class,
EarlyInitializationOnAnnotationFactoryBeanConfiguration.class)
.run((context) -> {
assertThat(EarlyInitializationFactoryBeanConfiguration.calledWhenNoFrozen).as("calledWhenNoFrozen")
.isFalse();
assertThat(context).hasBean("bar");
assertThat(context).hasSingleBean(ExampleBean.class);
});
}
private void hasBarBean(AssertableApplicationContext context) {
assertThat(context).hasBean("bar");
assertThat(context.getBean("bar")).isEqualTo("bar");
@ -352,6 +367,35 @@ class ConditionalOnBeanTests {
}
@Configuration(proxyBeanMethods = false)
static class EarlyInitializationFactoryBeanConfiguration {
static boolean calledWhenNoFrozen;
@Bean
@TestAnnotation
static FactoryBean<?> exampleBeanFactoryBean(ApplicationContext applicationContext) {
// NOTE: must be static and return raw FactoryBean and not the subclass so
// Spring can't guess type
ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext)
.getBeanFactory();
calledWhenNoFrozen = calledWhenNoFrozen || !beanFactory.isConfigurationFrozen();
return new ExampleFactoryBean();
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(annotation = TestAnnotation.class)
static class EarlyInitializationOnAnnotationFactoryBeanConfiguration {
@Bean
String bar() {
return "bar";
}
}
static class WithPropertyPlaceholderClassNameRegistrar implements ImportBeanDefinitionRegistrar {
@Override
@ -518,7 +562,7 @@ class ConditionalOnBeanTests {
}
@Target(ElementType.TYPE)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface TestAnnotation {