Spring源码分析-SpringBoot启动

一、启动流程

  1. createApplicationContext:

    构造器会初始化AnnotatedBeanDefinitionReaderClassPathBeanDefinitionScanner,在AnnotatedBeanDefinitionReader构造器中,会调用AnnotationConfigUtils.registerAnnotationConfigProcessors

  2. prepareContext

    1. postProcessApplicationContext

      • beanNameGenerator
      • resourceLoader
      • conversionService
    2. applyInitializers

    3. listeners.contextPrepared(context)

    4. load:在这里会将启动类的bd注册到容器,以便后边根据启动类导入

    5. refreshContext --> refresh:

      1. prepareRefresh

      2. obtainFreshBeanFactory --> refreshBeanFactory:

        refreshBeanFactory是个重载方法,分别对应纯注解启动的GenericApplicationContext,以及xml注入使用的AbstractRefreshableApplicationContext:loadBeanDefinitions

      3. prepareBeanFactory

      4. invokeBeanFactoryPostProcessors

      5. registerBeanPostProcessors:

        按顺序实例化bean并注册到容器:priorityOrdered->ordered->nonOrdered->internal

    6. onRefresh

    7. finishBeanFactoryInitialization

    8. afterRefresh

      1. callRunners:获取、排序并执行ApplicationRunnerCommandLineRunner

二、AbstractRefreshableApplicationContext:loadBeanDefinitions

--> XmlBeanDefinitionReader#loadBeanDefinitions:遍历资源(配置文件,例如xml),注册bd

--> XmlBeanDefinitionReader#doLoadBeanDefinitions

--> XmlBeanDefinitionReader#doLoadBeanDefinitions

--> XmlBeanDefinitionReader

doLoadDocument:返回解析好的Document

registerBeanDefinitions--> doRegisterBeanDefinitions --> parseBeanDefinitions

  1. parseDefaultElement:解析各种标签以及标签属性,生成bd,注册到容器:

    <bean class="com.xiaoxizi.spring.service.AccountServiceImpl"
          id="accountService"
          name="aaa"
          scope="singleton"
          abstract="false"
          parent="parent"
          autowire="byType"
          autowire-candidate="true"
          primary="true"
          depends-on="depends"
          init-method="init"
          destroy-method="destroy"
          factory-bean="factoryBean"
          factory-method="factoryMethod"
          lazy-init="false"
          >
        <description>一些描述</description>
        <constructor-arg ref="bean" value="固定值" type="参数类型" name="参数名称" index="索引"/>
        <property name="key1" value="固定值" ref="beanRef"/>
        <meta key="key1" value="固定值"/>
        <qualifier type="bean类型" value="限定的bean的名称"/>
        <lookup-method name="方法名" bean="bean名称"/>
        <replaced-method name="方法名" replacer="bean名称">
            <arg-type>参数类型,用于缺人唯一的方法</arg-type>
        </replaced-method>
    </bean>
    
    属性 作用
    class 指明bean所属的类
    id bean在ioc容器中的唯一标识,如果不填将取别名中的第一个
    name bean的别名
    scope bean的scope,一般日常开发都是使用默认的singleton单例,还有prototype多例。事实上web环境还有request和session。而且我们也可以自定义scope(之后会讲到的)
    abstract 是否是抽象的,抽象的bean不会被实例化,只能被继承,用的很少
    parent 指定父bean,可以结合abstract一起使用,当然parent指向的bean并不一定要是抽象的
    autowire 被自动装配的模式,有byType,byName等可选
    autowire-candidate 是否能被其他bean自动装配,false的话该bean将不能被其他bean注入,读者可以自行尝试一下
    primary 如果自动装配时匹配到多个bean,标记为primary的bean将被优先注入。
    depends-on 依赖,依赖的bean将会先被实例化
    init-method bean实例化之后将会调用的方法
    destroy-method bean销毁时将会调用的方法,需要主要的是,只有单例的bean,IOC容器才持有其引用,IOC容器销毁 --> bean销毁时才会触发这个方法。
    factory-bean 工厂bean的名称,需要与factory-method结合使用,创建bean时将会调用factory-bean.factory-method()来获取当前类实例。
    factory-method 工厂bean方法,其实@Bean注解就是通过factory-bean、factory-method属性的功能实现的。
    lazy-init 是否是懒加载的
  2. parseCustomElement:

    1. getNamespaceURI(ele):获取标签对应的名称空间

    2. readerContext.getNamespaceHandlerResolver().resolve(namespaceUri):根据名称空间获取对应的处理器

      1. getHandlerMappings:实际是去META-INF/spring.handlers文件加载ns->handler的键值对到map中

      2. Object handlerOrClassName = handlerMappings.get(namespaceUri):获取出来的可能是个handler对象,或者是一个类名

        如果是类名(以ContextNamespaceHandler为例):

        namespaceHandler = BeanUtils.instantiateClass(handlerClass)

        namespaceHandler.init:

        ​ 注册一系列的Parser:

        ​ registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser())

        ​ ...

        handlerMappings.put(namespaceUri, namespaceHandler)

    3. handler.parse(以ContextNamespaceHandler为例):实际调用的是父类NamespaceHandlerSupport的方法

      1. findParserForElement:从之前注册的一系列parser中根据标签获取
      2. parser.parse:
      3. 获取basePackage
      4. 获取并配置ClassPathBeanDefinitionScanner
      5. scanner.doScan:返回一个bd集合
        findCandidateComponents(basePackage)
      6. 遍历每个bd:
        AnnotationConfigUtils.processCommonDefinitionAnnotations:处理@lazy@Primary@dependsOn@role@description等注解
      7. registerBeanDefinition
      8. registerComponents:AnnotationConfigUtils.registerAnnotationConfigProcessors
        ConfigurationClassPostProcessor:处理配置类
      9. AutowiredAnnotationBeanPostProcessor处理@Autowire,@Value
      10. CommonAnnotationBeanPostProcessor:处理@Resource、@PostConstruct、@PreDestroy
      11. ...
posted @ 2023-05-27 13:51  LEVRY  阅读(78)  评论(0)    收藏  举报