【Spring】重复的beanName覆盖原则(九)

  在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 

 

上一篇:Spring单例模式


下一篇:Android View的几个位置坐标关系