zoukankan      html  css  js  c++  java
  • Springboot源码 bean的注册

    1、这个过程发生在spring工厂refresh方法的invokeBeanFactoryPostProcessors中,取出ConfigurationClassPostProcessor这个BeanFactoryPostProcessors(也是一个BeanDefinitionRegistry类型),调用postProcessBeanDefinitionRegistry方法。

    2、ConfigurationClassPostProcessor被添加到spring工厂是发生在AnnotationConfigServletWebServerApplicationContext的构造方法中new AnnotatedBeanDefinitionReader() --->registerAnnotationConfigProcessors() ---> 向spring工厂注册ConfigurationClassPostProcessor

    3、postProcessBeanDefinitionRegistry--->processConfigBeanDefinitions方法,获取当前工厂中所有的beanDefinition,检测是否是配置类,是否是配置类是看有没有以下注解:@Configuration、@Component、@ComponentScan、@Import、@ImportResource、以及方法中有没有被@Bean注解的。如果是配置类的话(此时一般来讲,配置类只有SpringApplication.run方法放进来的参数,一般就是配置类),进入while循环,其实一般不会循环而是执行一次,调用parser.parse,再调用this.reader.loadBeanDefinitions(parser.getConfigurationClasses())。

    4、parser.parse---processConfigurationClass方法开始会检测OnCondition***,再在循环中对当前类以及所有父类执行doProcessConfigurationClass,再把当前类放入parser的configurationClasses属性中。

    5、doProcessConfigurationClass方法中,如果当前类被Component注解了就执行processMemberClasses处理内部类,接下来处理@PropertySource、@ComponentScan、@Import 、@ImportResource、@Bean 注解,

    6、processMemberClasses方法处理内部类,还是先看该内部类是不是配置类,如果是的话,执行processConfigurationClass方法。

    7、@ComponentScan的处理是扫描指定的包中的类,如果被@Componet注解,执行parse方法。

    8、@Import:processImports方法判断:注解中指定的类

         a、如果实现了ImportSelector接口,会被实例化,再判断,如果又实现了DeferredImportSelector接口,这个类会被放到parser的deferredImportSelectorHandler属性中。如果没有,会调用selectImports方法,对返回值再调用processImports方法。

         b、如果实现了ImportBeanDefinitionRegistrar接口,这个类也会被实例化,并被放到configClass的importBeanDefinitionRegistrars属性中。

         c、如果以上的接口都没有实现,那么甚至不判断符不符合配置类的条件,直接被当作配置类调用processConfigurationClass方法。

    9、@Bean注解的方法会被封装成BeanMethods,放到parser的beanMethods属性中。

    注意:6-9四个步骤是对于配置类和它的所有父类(除了父类以java.***开头的类,也就是rt.jar下面java包里的)

    上面的流程中,很多类被放到parser的属性(多是map和set)中了,这些东西在this.reader.loadBeanDefinitions(parser.getConfigurationClasses())中处理:

    10、loadBeanDefinitions:其中有方法:registerBeanDefinitionForImportedConfigurationClass; loadBeanDefinitionsForBeanMethod; loadBeanDefinitionsFromRegistrars;

    11、registerBeanDefinitionForImportedConfigurationClass:一个配置类,自己是要被收入工厂的。进入本方法之前,会对configClass做一个判断,只有isImported为true,也就是被被别的类导入的ConfigClass才会被处理,回顾之前的代码,只有6和8c两种途径引入的类的isImported为ture。

    12、loadBeanDefinitionsFromRegistrars:调用之前已经实例化的8b途径中被导入的类的registerBeanDefinitions方法,向工厂注册类。

    13、loadBeanDefinitionsForBeanMethod: 主要是在beanDefinition中设置了factoryMethodName,回顾一下spring源码的getBean--->doCreateBean--->createBeanInstance方法中,在寻找并调用构造方法之前,判断如果factoryMethodName不为空,那么调用instantiateUsingFactoryMethod方法,使用factoryMethod而不是构造方法生成bean。可见factoryMethod和构造方法是一个等级的,那么自动注入在这里也是存在的。

    14、8a途径的处理在parse方法的最后,processConfigurationClass的下面,this.deferredImportSelectorHandler.process(),点进去看,最后也是调用的processImports方法,处理返回的一些类。

    15、@ImportResource和@PropertySource平时不太能用到,所以略过。

    16、a:一个配置类如果没有被@component注解,其内部类以及其父类的内部类不会被当作配置类。但是如果该类是一个被@Component注解了的配置类的父类,其内部类满足配置类的条件后就会被注册,即使该类本身并没有被@Component注解。b:一个类即使满足配置类的条件,但是如果仅仅作为另一个配置类的父类,是不会被注册的。c:@ComponentScan扫描到的、parse方法进入之前放进candidates中的,都要检测该类是不是配置类。但是@Import的8c途径导入的类,不需要检测。

     

  • 相关阅读:
    SQL分组统计
    实用DOS命令
    Shadertoy 教程 Part 6 使用光线步进算法创建3D场景
    浅谈web前端优化
    如何搭建一套前端监控系统
    with(this)中with的用法及其优缺点
    vue mvvm
    散列表(哈希表)(二)散列函数的构造方法
    作为程序员,你最常上的网站是什么
    散列表(哈希表)(一)散列表的概念
  • 原文地址:https://www.cnblogs.com/chuliang/p/11107566.html
Copyright © 2011-2022 走看看