Когда имена bean-компонентов Spring дублируются, когда будет выдано исключение?

Меня смущает то, что когда я использую метод @Bean для внедрения двух bean-компонентов с одинаковым именем в контейнер и запуска контекста приложения Spring, это удается. Однако, если я использую @Component для внедрения двух bean-компонентов с одинаковым именем в контейнер и запуска контекста, это вызывает исключение. Почему это происходит и как мне это понимать?

example1: метод с именем beanA будет выполнен, а beanB будет проигнорирован, запуск контекста приложения Spring будет успешным. Он всегда выполняет вышеуказанный метод?

@SpringBootApplication
public class LuckySpringBootStarterApplication {

    @Bean(name = "a")
    public String beanA() {
        return "a";
    }

    @Bean(name = "a")
    public String beanB() {
        return "b";
    }

    public static void main(String[] args) {
        SpringApplication.run(LuckySpringBootStarterApplication.class, args);
    }
}

example2 выдаст исключение

@SpringBootApplication
public class LuckySpringBootStarterApplication {

    @Component("a")
    static class A {

    }

    @Component("a")
    static class B {

    }

    public static void main(String[] args) {
        SpringApplication.run(LuckySpringBootStarterApplication.class, args);
    }
}
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [space.luckycurve.LuckySpringBootStarterApplication]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:179) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:417) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:290) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:349) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:118) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:789) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:607) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.2.jar:3.3.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.2.jar:3.3.2]
    at space.luckycurve.LuckySpringBootStarterApplication.main(LuckySpringBootStarterApplication.java:21) ~[classes/:na]
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.3.2.jar:3.3.2]
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'a' for bean class [space.luckycurve.LuckySpringBootStarterApplication$B] conflicts with existing, non-compatible bean definition of same name and class [space.luckycurve.LuckySpringBootStarterApplication$A]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:361) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:288) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:306) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:246) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:197) ~[spring-context-6.1.11.jar:6.1.11]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:165) ~[spring-context-6.1.11.jar:6.1.11]
    ... 16 common frames omitted
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
57
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Поведение, которое вы наблюдаете, связано с разными способами, которыми Spring обрабатывает определения bean-компонентов с помощью методов @Bean и классов @Component.

Обработка метода @Bean:

Методы @Bean обрабатываются Spring во время выполнения как часть обработки класса конфигурации. Когда вы определяете несколько методов @Bean с одинаковым именем, последний метод перезаписывает предыдущие. Это связано с тем, что Spring считает методы @Bean более явными и управляемыми в контексте класса конфигурации.

@Обработка компонентов:

@Component используется для автоматического обнаружения и регистрации bean-компонентов во время сканирования компонентов. Когда обнаруживаются два класса @Component с одинаковым именем, Spring не может решить, какой из них использовать, и вызывает конфликт. Это связано с тем, что сканирование @Component не обладает такой же гибкостью во время выполнения для обработки повторяющихся имен, как методы @Bean.

Спасибо за ваш ответ. Не могли бы вы предоставить мне ссылки на соответствующую документацию? Я просмотрел часть официальной документации Spring, но не нашел однозначного ответа. Меня особенно интересует понимание конкретного процесса загрузки Spring.

LuckyCurve 03.08.2024 14:32
Ответ принят как подходящий

Я отправил проблему в Spring Framework, и эта проблема добавлена ​​к этапу 6.2.0-M7. Вы можете проверить последний прогресс по следующей ссылке: https://github.com/spring-projects/spring-framework/ выпуски/33330

Другие вопросы по теме