在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 "' *es 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