Spring之两个bean的name相同会报错吗

  首先要回答这个问题要看spring什么版本,以及使用的是什么方式初始化spring容器。先说结论,如果是xml的方式,还要分两种情况

  1 所有的bean都定义在同一个xml中,这种情况下会直接报错

  2 两个相同名字的bean定义在两个xml文件中,一个xml文件通过import进行引用另一个,这种方式会进行覆盖。

  

  不过,现在使用spring基本没有在使用xml方式的了,都是通过@Configuration的方式,比如我们有如下的代码

package com.example.demo.configuration;

import com.example.demo.beans.Book;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AnnotationConfiguration {
    public AnnotationConfiguration() {
        System.out.println("初始化");
    }

    @Bean("book1")
    public Book book()
    {
        Book book=new Book();
        book.setName("java++");
        return book;
    }

    @Bean("book1")
    public Book book1()
    {
        Book book=new Book();
        book.setName("java");
        return book;
    }

}

  下面来分析@Bean的解析过程

  1 ConfigurationClassParser.doProcessConfigurationClass 代码片段

// Process individual @Bean methods
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

  retrieveBeanMethodMetadata方法在这里就不详细分析了,结论就是会把两个@Bean注解的方法包成MethodMetadata,注意这里会包成两个方法

  2  ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod

  第一步做的只是解析@Configuration类,还没有进行BeanDefinition的生成。

  真正进行生成BeanDefinition的地方是在 ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod

  

// Has this effectively been overridden before (e.g. via XML)?
        if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
            if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
                throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
                        beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
                        "' clashes with bean name for containing configuration class; please make those names unique!");
            }
            return;
        }

  其中的代码段,如果一个beanName已经被处理过了,也就是 isOverriddenByExistingDefinition 返回为true

  就直接return。

  抛异常的地方的逻辑是,@Bean所在的@Configuration的classname是否和beanName相同,我们这里的classname是 AnnotationConfiguration

  所以一般情况下都不会走到抛异常的逻辑里 

posted on 2022-06-02 12:04  MaXianZhe  阅读(948)  评论(0编辑  收藏  举报

导航