【Spring】IOC:初始化源码流程(下)注册 BeanDefinition

Bertha 。 2022-10-31 01:46 260阅读 0赞

在这里插入图片描述

向IOC容器注册在第二步解析好的 BeanDefinition,这个过程是通过 BeanDefinitionRegistery 接口来实现的。在 IOC 容器内部其实是将第二个过程解析得到的 BeanDefinition 注入到一个 HashMap 容器中,IOC 容器就是通过这个 HashMap 来维护这些 BeanDefinition 的。

在这里需要注意的一点是这个过程并没有完成依赖注入,依赖注册是发生在应用第一次调用 getBean() 向容器索要 Bean 时。当然我们可以通过设置预处理,即对某个 Bean 设置 lazyinit 属性,那么这个 Bean 的依赖注入就会在容器初始化的时候完成。

1.分配注册策略 (BeanDefinitionReaderUtils)

让我们继续跟踪程序的执行顺序,接下来我们来分析 DefaultBeanDefinitionDocumentReader 对 Bean 定义转换的 Document 对象解析的流程中,在其 parseDefaultElement()方法中完成对 Document 对象的解析后,得到封装 BeanDefinition 的 BeanDefinitionHold 对象,然后调用BeanDefinitionReaderUtils 的 registerBeanDefinition()方法向 IOC 容器注册解析的 Bean。BeanDefinitionReaderUtils的注册的源码如下:

registerBeanDefinition()

将解析的BeanDefinitionHold注册到容器中

  1. public static void registerBeanDefinition(
  2. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
  3. throws BeanDefinitionStoreException {
  4. // Register bean definition under primary name.
  5. // 获取解析的BeanDefinition的名称
  6. String beanName = definitionHolder.getBeanName();
  7. // 向IOC容器注册BeanDefinition
  8. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
  9. // Register aliases for bean name, if any.
  10. // 如果解析的BeanDefinition有别名,向容器为其注册别名
  11. String[] aliases = definitionHolder.getAliases();
  12. if (aliases != null) {
  13. for (String alias : aliases) {
  14. registry.registerAlias(beanName, alias);
  15. }
  16. }
  17. }

当调用BeanDefinitionReaderUtils向 IOC 容器注册解析的BeanDefinition时,真正完成注册功DefaultListableBeanFactory

2.向容器注册 (DefaultListableBeanFactory)

DefaultListableBeanFactory 中使用一个 HashMap 的集合对象存放 IOC 容器中注册解析的 BeanDefinition,向IOC 容器注册的主要源码如下:
20201208155438309.png

registerBeanDefinition()

向IOC容器注册解析的BeanDefiniton

  1. @Override
  2. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {
  3. Assert.hasText(beanName, "Bean name must not be empty");
  4. Assert.notNull(beanDefinition, "BeanDefinition must not be null");
  5. // 校验解析的BeanDefiniton
  6. if (beanDefinition instanceof AbstractBeanDefinition) {
  7. try {
  8. ((AbstractBeanDefinition) beanDefinition).validate();
  9. }
  10. catch (BeanDefinitionValidationException ex) {
  11. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  12. "Validation of bean definition failed", ex);
  13. }
  14. }
  15. BeanDefinition oldBeanDefinition;
  16. oldBeanDefinition = this.beanDefinitionMap.get(beanName);
  17. if (oldBeanDefinition != null) {
  18. if (!isAllowBeanDefinitionOverriding()) {
  19. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  20. "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName
  21. + "': There is already [" + oldBeanDefinition + "] bound.");
  22. }
  23. else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
  24. // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or
  25. // ROLE_INFRASTRUCTURE
  26. if (this.logger.isWarnEnabled()) {
  27. this.logger.warn("Overriding user-defined bean definition for bean '" + beanName
  28. + "' with a framework-generated bean definition: replacing [" +oldBeanDefinition
  29. + "] with [" + beanDefinition + "]");
  30. }
  31. }
  32. else if (!beanDefinition.equals(oldBeanDefinition)) {
  33. if (this.logger.isInfoEnabled()) {
  34. this.logger.info("Overriding bean definition for bean '" + beanName
  35. + "' with a different definition: replacing [" + oldBeanDefinition +"] with ["
  36. + beanDefinition + "]");
  37. }
  38. }
  39. else {
  40. if (this.logger.isDebugEnabled()) {
  41. this.logger.debug("Overriding bean definition for bean '" + beanName
  42. + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with ["
  43. + beanDefinition + "]");
  44. }
  45. }
  46. this.beanDefinitionMap.put(beanName, beanDefinition);
  47. }
  48. else {
  49. if (hasBeanCreationStarted()) {
  50. // Cannot modify startup-time collection elements anymore (for stable iteration)
  51. // 注册的过程中需要线程同步,以保证数据的一致性
  52. synchronized (this.beanDefinitionMap) {
  53. this.beanDefinitionMap.put(beanName, beanDefinition);
  54. List<String> updatedDefinitions = new ArrayList<>
  55. (this.beanDefinitionNames.size() + 1);
  56. updatedDefinitions.addAll(this.beanDefinitionNames);
  57. updatedDefinitions.add(beanName);
  58. this.beanDefinitionNames = updatedDefinitions;
  59. if (this.manualSingletonNames.contains(beanName)) {
  60. Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
  61. updatedSingletons.remove(beanName);
  62. this.manualSingletonNames = updatedSingletons;
  63. }
  64. }
  65. }
  66. else {
  67. // Still in startup registration phase
  68. this.beanDefinitionMap.put(beanName, beanDefinition);
  69. this.beanDefinitionNames.add(beanName);
  70. this.manualSingletonNames.remove(beanName);
  71. }
  72. this.frozenBeanDefinitionNames = null;
  73. }
  74. // 检查是否有同名的BeanDefinition已经在IOC容器中注册
  75. if (oldBeanDefinition != null || containsSingleton(beanName)) {
  76. // 重置所有已经注册过的BeanDefinition的缓存
  77. resetBeanDefinition(beanName);
  78. }
  79. }

至此,Bean配置信息中配置的Bean被解析过后,已经注册到IOC 容器中,被容器管理起来,真正完成了 IOC 容器初始化所做的全部工作。现在 IOC 容器中已经建立了整个 Bean 的配置信息,这些BeanDefinition信息已经可以使用,并且可以被检索。

IOC 容器的作用就是对这些注册的Bean定义信息进行处理和维护。这些的注册的 Bean定义信息是IOC 容器控制反转的基础,正是有了这些注册的数据,容器才可以进行依赖注入。

发表评论

表情:
评论列表 (有 0 条评论,260人围观)

还没有评论,来说两句吧...

相关阅读