From ee7555750ebb8e7b53ba2051ff525f3112f830a3 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 6 Jan 2020 16:33:38 +0100 Subject: [PATCH] Add ComponentScan#nameGenerator alias on @SpringBootApplication This commit allows to customize the default BeanNameGenerator for scanned components using @SpringBootApplication. Closes gh-19346 --- .../autoconfigure/SpringBootApplication.java | 19 +++++++++++++ .../SpringBootApplicationTests.java | 27 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SpringBootApplication.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SpringBootApplication.java index 2f7c10f0dc97..8cd92b8df621 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SpringBootApplication.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SpringBootApplication.java @@ -23,8 +23,11 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.context.TypeExcludeFilter; +import org.springframework.context.annotation.AnnotationBeanNameGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; @@ -104,6 +107,22 @@ @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class[] scanBasePackageClasses() default {}; + /** + * The {@link BeanNameGenerator} class to be used for naming detected components + * within the Spring container. + *

+ * The default value of the {@link BeanNameGenerator} interface itself indicates that + * the scanner used to process this {@code @SpringBootApplication} annotation should + * use its inherited bean name generator, e.g. the default + * {@link AnnotationBeanNameGenerator} or any custom instance supplied to the + * application context at bootstrap time. + * @return {@link BeanNameGenerator} to use + * @see SpringApplication#setBeanNameGenerator(BeanNameGenerator) + * @since 2.3.0 + */ + @AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator") + Class nameGenerator() default BeanNameGenerator.class; + /** * Specify whether {@link Bean @Bean} methods should get proxied in order to enforce * bean lifecycle behavior, e.g. to return shared singleton bean instances even in diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/SpringBootApplicationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/SpringBootApplicationTests.java index d4260e10f4bd..be6997c9a057 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/SpringBootApplicationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/SpringBootApplicationTests.java @@ -18,6 +18,9 @@ import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.beans.factory.support.DefaultBeanNameGenerator; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotationAttributes; @@ -28,6 +31,7 @@ * Tests for {@link SpringBootApplication @SpringBootApplication}. * * @author Andy Wilkinson + * @author Stephane Nicoll */ class SpringBootApplicationTests { @@ -45,6 +49,20 @@ void proxyBeanMethodsCanBeDisabled() { assertThat(attributes.get("proxyBeanMethods")).isEqualTo(false); } + @Test + void nameGeneratorDefaultToBeanNameGenerator() { + AnnotationAttributes attributes = AnnotatedElementUtils + .getMergedAnnotationAttributes(DefaultSpringBootApplication.class, ComponentScan.class); + assertThat(attributes.get("nameGenerator")).isEqualTo(BeanNameGenerator.class); + } + + @Test + void nameGeneratorCanBeSpecified() { + AnnotationAttributes attributes = AnnotatedElementUtils + .getMergedAnnotationAttributes(CustomNameGeneratorConfiguration.class, ComponentScan.class); + assertThat(attributes.get("nameGenerator")).isEqualTo(TestBeanNameGenerator.class); + } + @SpringBootApplication static class DefaultSpringBootApplication { @@ -55,4 +73,13 @@ static class NoBeanMethodProxyingSpringBootApplication { } + @SpringBootApplication(nameGenerator = TestBeanNameGenerator.class) + static class CustomNameGeneratorConfiguration { + + } + + static class TestBeanNameGenerator extends DefaultBeanNameGenerator { + + } + }