在Springboot项目下面是如何组装Bean的(中)-BeanDefinitions加载

ConfigurationClassPostProcessor#parser.parse(candidates)执行完成之后,parser对象中的configurationClasses从0个变成了45个,所以可以知道parser.parse(candidates)是根据传入的启动类找到了某些配置类

图片

现在来看看parse方法,第一个解析的就是启动类:

图片

在doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)这个方法中:

  1. processMemberClasses(configClass, sourceClass);解析内部类;

  2. Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);解析@ComponentScan注解

  3. processImports(configClass,sourceClass,getImports(sourceClass), true);递归解析@Import注解,下图是启动类找到的三个需要Import的配置类
    图片

    下面是两处递归处理:

    图片

    图片

    这部分代码很重要,至今还有点雾里看花,一堆循环,一堆递归的...

  4. processPropertySource(propertySource);解析@PropertySource注解

  5. Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);解析标注有@Bean的方法

  6. processInterfaces(configClass, sourceClass);递归解析所有改bean实现的接口

  7. sourceClass.getMetadata().getSuperClassName();解析父类

  8. return null;跳出do while循环,完成一个配置类的识别,并放到configurationClasses中:

    图片

 

parser.parse(candidates)处理完成后找到了45个配置类:

图片

 

------^_^------漂亮的分隔符------^_^------

 

找到了相关配置类之后循环交个ConfigurationClassBeanDefinitionReader去解析:

图片

ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass这个方法里面:

a. registerBeanDefinitionForImportedConfigurationClass: 主要判断bean的scope, 给bean取名,是否延迟加载,是否启动类,依赖的bean,解析完会先注册到beanDefinitionMap.

b. loadBeanDefinitionsForBeanMethod: 这里是解析当前类是否有@Bean注解的方法,因为这样也是可以注册一个bean的,解析完成同样放到beanDefinitionMap

c. loadBeanDefinitionsFromImportedResources: 解析@ImportResource注解(不常用,忽略)

d. loadBeanDefinitionsFromRegistrars: 解析需要扫描的包路径,最终会交给AutoConfigurationPackages#register去完成,解析完成同样放到beanDefinitionMap(不过此时放的并不是具体的某个Class的BeanDefinition,而是AutoConfigurationPackages对象)

 

DefaultListableBeanFactory#registerBeanDefinition,BeanDefinition解析完成之后,最后会把解析结果放到beanDefinitionMap中

图片

 

下图中的this.reader.loadBeanDefinitions(configClasses);执行完成后

图片

可以看到beanFactory中已经存在所有的BeanDefinition了:

图片

 

总结:BeanDefinition的加载过程主要有两个阶段:

    1. parser.parse识别是否Configuration Bean

    2. loadBeanDefinitions(configClasses)加载并解析,存储到beanDefinitionMap中


      更多了解请关注一米源码公众号并回复SpringBoot或https://itproject-manager.com/

posted on 2021-04-05 08:54  itproject-manager  阅读(314)  评论(0编辑  收藏  举报