[JAVA] Personnalisez le nom du bean défini par Spring component-scan

Lors du développement avec le composant-scan de Spring (même par défaut dans Boot), le nom du bean est automatiquement attribué, il est donc facile de couvrir le nom.

SampleSpringBoot
├── SampleSpringBootApplication.java
└── controller
    ├── fuga
    │   └── HelloController.java
    └── hoge
        └── HelloController.java

Dans ce cas, fuga.HelloController et hoge.HelloController ont le nom de bean ** helloController **, ce qui signifie qu'ils ne peuvent pas être démarrés car ils sont couverts.

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [net.sinsengumi.SampleSpringBoot.SampleSpringBootApplication]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'helloController' for bean class [net.sinsengumi.SampleSpringBoot.controller.hoge.HelloController] conflicts with existing, non-compatible bean definition of same name and class [net.sinsengumi.SampleSpringBoot.controller.fuga.HelloController]
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:181) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:270) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:93) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.4.RELEASE.jar:1.5.4.RELEASE]
	at net.sinsengumi.SampleSpringBoot.SampleSpringBootApplication.main(SampleSpringBootApplication.java:10) [classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_112]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_112]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_112]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_112]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.5.4.RELEASE.jar:1.5.4.RELEASE]
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'helloController' for bean class [net.sinsengumi.SampleSpringBoot.controller.hoge.HelloController] conflicts with existing, non-compatible bean definition of same name and class [net.sinsengumi.SampleSpringBoot.controller.fuga.HelloController]
	at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:345) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:283) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:135) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:287) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:245) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:198) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:167) ~[spring-context-4.3.9.RELEASE.jar:4.3.9.RELEASE]
	... 18 common frames omitted

Si vous souhaitez éviter cela, vous pouvez définir le nom du bean lors de la définition du composant.

// fuga.HelloController
@RestController("fugaHelloController")

// hoge.HelloController
@RestController("hogeHelloController")

Cependant, c'est trop ennuyeux, c'est donc une bonne idée de tout régler en même temps et de ne pas le couvrir. Ceci est possible en utilisant le ** nameGenerator ** de component-scan. Si vous voulez vous assurer de ne pas souffrir en général, vous pouvez penser au FQCN. Mais je ne pense pas que ce soit un problème.

public class FQCNBeanNameGenerator extends AnnotationBeanNameGenerator {

    @Override
    protected String buildDefaultBeanName(BeanDefinition definition) {
        return definition.getBeanClassName();
    }
}
@SpringBootApplication
@ComponentScan(nameGenerator = FQCNBeanNameGenerator.class)
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Désormais, les noms de bean seront net.sinsengumi.SampleSpringBoot.controller.fuga.HelloController et net.sinsengumi.SampleSpringBoot.controller.hoge.HelloController et ne seront pas couverts.

Spring veut que ce comportement soit la valeur par défaut.

Recommended Posts

Personnalisez le nom du bean défini par Spring component-scan
Partie 4: Personnalisez le comportement de la connexion OAuth 2.0 prise en charge par Spring Security 5
Lorsque le nom de la classe du bean est dupliqué
Obtenez le nom de classe et le nom de méthode du contrôleur exécuté par le HandlerInterceptor de Spring Boot
Empêcher les erreurs dans le nom de l'enregistreur en copiant
Le nom officiel de Spring MVC est Spring Web MVC
[Kotlin] Récupère le nom de l'argument du constructeur par réflexion
Obtenez le nom d'anime de ce terme en grattant