在Spring中,可以有由于存在重复的beanName会有一些问题
下面看看,Spring是怎么处理重复的beanName的
1、Spring容器内置了 ConfigurationClassPostProcessor 配置类工厂bean后置处理器,在Bean工厂准备好后,调用 postProcessBeanDefinitionRegistry() 方法来后置处理bean工厂
1 @Override
2 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
3 int registryId = System.identityHashCode(registry);
4 if (this.registriesPostProcessed.contains(registryId)) {
5 throw new IllegalStateException(
6 "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
7 }
8 if (this.factoriesPostProcessed.contains(registryId)) {
9 throw new IllegalStateException(
10 "postProcessBeanFactory already called on this post-processor against " + registry);
11 }
12 // 给后置处理器,添加注册ID
13 this.registriesPostProcessed.add(registryId);
14 // 解析配置的bean定义
15 processConfigBeanDefinitions(registry);
16 }
2、processConfigBeanDefinitions() 处理配置bean定义
1 public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
2
3 ......
4
5 // Parse each @Configuration class
6 // 创建一个配置类解析器对象
7 ConfigurationClassParser parser = new ConfigurationClassParser(
8 this.metadataReaderFactory, this.problemReporter, this.environment,
9 this.resourceLoader, this.componentScanBeanNameGenerator, registry);
10
11 // 创建一个集合用于保存配置类BeanDefinitionHolder集合默认长度是配置类集合的长度
12 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
13 // 创建一个集合用于保存已经解析的配置类,长度默认为解析出来默认的配置类的集合长度
14 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
15 //do while 会进行第一次解析
16 do {
17 // 使用配置类解析器,解析配置类
18 parser.parse(candidates);
19 // 使用配置类解析器,验证
20 parser.validate();
21 // 解析出来的配置类,即从解析器的配置类属性中获取解析出来的配置类
22 Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
23 configClasses.removeAll(alreadyParsed);
24
25 // Read the model and create bean definitions based on its content
26 if (this.reader == null) {
27 this.reader = new ConfigurationClassBeanDefinitionReader(
28 registry, this.sourceExtractor, this.resourceLoader, this.environment,
29 this.importBeanNameGenerator, parser.getImportRegistry());
30 }
31 // 真正的把解析出来的配置类注册到容器中
32 this.reader.loadBeanDefinitions(configClasses);
33
34 ....
35 }
36 // 存在没有解析过的 需要循环解析
37 while (!candidates.isEmpty());
38
39 .....
40 }
3、解析出来后,通过 loadBeanDefinitions() 方法,把bean定义注册到容器中
loadBeanDefinitions() -> loadBeanDefinitionsForConfigurationClass() -> loadBeanDefinitionsForBeanMethod()
加载被@Bean修饰的方法 bean定义时
1 // 从Bean方法中加载Bean定义
2 private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
3
4 ......
5
6 // Has this effectively been overridden before (e.g. via XML)?
7 // 是否覆盖已经存在的Bean定义
8 /**
9 * 0、不存在相同Bean定义名称的,则返回false。继续添加bean定义
10 * 1、配置类的名字相同,则报错
11 * 2、同一个配置类中的@Bean名字相同,则返回true,意思是以先加载的@Bean方法为准
12 * 3、不同的配置类中的@Bean名字相同,则返回false,意思是可以被覆盖,已后被加载的@Bean方法为准
13 */
14 if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
15 // 配置类名称相同报异常
16 if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
17 throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
18 beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
19 "' clashes with bean name for containing configuration class; please make those names unique!");
20 }
21 return;
22 }
23
24 // 创建配置类的Bean定义
25 ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
26
27 ......
28
29 // 注册Bean定义
30 this.registry.registerBeanDefinition(beanName, beanDefToRegister);
31 }
4、isOverriddenByExistingDefinition() 判断是否覆盖已经存在的Bean定义的方法
1 // 是否覆盖已经存在的Bean定义
2 protected boolean isOverriddenByExistingDefinition(BeanMethod beanMethod, String beanName) {
3 if (!this.registry.containsBeanDefinition(beanName)) {
4 return false;
5 }
6 BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName);
7
8 // 存在的Bean定义 是否是 配置类Bean定义类型
9 if (existingBeanDef instanceof ConfigurationClassBeanDefinition) {
10 ConfigurationClassBeanDefinition ccbd = (ConfigurationClassBeanDefinition) existingBeanDef;
11 // 是否是同一个配置类名
12 if (ccbd.getMetadata().getClassName().equals(
13 beanMethod.getConfigurationClass().getMetadata().getClassName())) {
14 if (ccbd.getFactoryMethodMetadata().getMethodName().equals(ccbd.getFactoryMethodName())) {
15 ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName());
16 }
17 return true;
18 }
19 else {
20 return false;
21 }
22 }
23
24 // 属性扫描生成的Bean定义
25 if (existingBeanDef instanceof ScannedGenericBeanDefinition) {
26 return false;
27 }
28
29 // 现有的bean定义bean是否标记为框架生成的bean
30 if (existingBeanDef.getRole() > BeanDefinition.ROLE_APPLICATION) {
31 return false;
32 }
33
34
35 if (this.registry instanceof DefaultListableBeanFactory &&
36 !((DefaultListableBeanFactory) this.registry).isAllowBeanDefinitionOverriding()) {
37 throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
38 beanName, "@Bean definition illegally overridden by existing bean definition: " + existingBeanDef);
39 }
40 if (logger.isDebugEnabled()) {
41 logger.debug(String.format("Skipping bean definition for %s: a definition for bean '%s' " +
42 "already exists. This top-level bean definition is considered as an override.",
43 beanMethod, beanName));
44 }
45 return true;
46 }
5、注册bean定义方法 registerBeanDefinition()
1 // 在Bean工厂中注册bean定义
2 @Override
3 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
4 throws BeanDefinitionStoreException {
5
6 Assert.hasText(beanName, "Bean name must not be empty");
7 Assert.notNull(beanDefinition, "BeanDefinition must not be null");
8
9 // 判断bean定义 属于抽象的bean定义
10 if (beanDefinition instanceof AbstractBeanDefinition) {
11 try {
12 // 验证bean定义
13 ((AbstractBeanDefinition) beanDefinition).validate();
14 }
15 catch (BeanDefinitionValidationException ex) {
16 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
17 "Validation of bean definition failed", ex);
18 }
19 }
20
21 // 根据bean名字获取已经存在的bean定义
22 BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
23 if (existingDefinition != null) {
24 // 是否允许覆盖Bean定义 allowBeanDefinitionOverriding默认值为true
25 if (!isAllowBeanDefinitionOverriding()) {
26 throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
27 }
28 else if (existingDefinition.getRole() < beanDefinition.getRole()) {
29 // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
30 if (logger.isInfoEnabled()) {
31 logger.info("Overriding user-defined bean definition for bean '" + beanName +
32 "' with a framework-generated bean definition: replacing [" +
33 existingDefinition + "] with [" + beanDefinition + "]");
34 }
35 }
36 else if (!beanDefinition.equals(existingDefinition)) {
37 if (logger.isDebugEnabled()) {
38 logger.debug("Overriding bean definition for bean '" + beanName +
39 "' with a different definition: replacing [" + existingDefinition +
40 "] with [" + beanDefinition + "]");
41 }
42 }
43 else {
44 if (logger.isTraceEnabled()) {
45 logger.trace("Overriding bean definition for bean '" + beanName +
46 "' with an equivalent definition: replacing [" + existingDefinition +
47 "] with [" + beanDefinition + "]");
48 }
49 }
50 this.beanDefinitionMap.put(beanName, beanDefinition);
51 }
52 else {
53 // 判断Bean工厂是否已经开始创建Bean了
54 if (hasBeanCreationStarted()) {
55 // Cannot modify startup-time collection elements anymore (for stable iteration)
56 synchronized (this.beanDefinitionMap) {
57 this.beanDefinitionMap.put(beanName, beanDefinition);
58 List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
59 updatedDefinitions.addAll(this.beanDefinitionNames);
60 updatedDefinitions.add(beanName);
61 this.beanDefinitionNames = updatedDefinitions;
62 removeManualSingletonName(beanName);
63 }
64 }
65 else {
66
67 // 放入到bean工厂的bean定义的Map集合中
68 this.beanDefinitionMap.put(beanName, beanDefinition);
69 // 添加beanName 到 名称集合中
70 this.beanDefinitionNames.add(beanName);
71 // 删除手动单例名称
72 removeManualSingletonName(beanName);
73 }
74 this.frozenBeanDefinitionNames = null;
75 }
76
77 if (existingDefinition != null || containsSingleton(beanName)) {
78 // 重置Bean定义
79 resetBeanDefinition(beanName);
80 }
81