• Spring 启动 Bean加载流程


    1. spring 启动类 SpringApplication.run(PpApplication.class,args)
    2. AnnotationConfigEmbeddedWebApplicationContext context = createAndRefreshContext(listeners, applicationArguments);context里面默认带有一个beanFactory,而这个beanFactory的类型为DefaultListableBeanFactory
    3. refresh
      1. 该方法中,我们这次需要注意的地方有两个:
        1、invokeBeanFactoryPostProcessors(beanFactory);
        2、finishBeanFactoryInitialization(beanFactory);
        两处传入的beanFactory为上面的context中的DefaultListableBeanFactory。

      2.  1 @Override
         2 public void refresh() throws BeansException, IllegalStateException {
         3   synchronized (this.startupShutdownMonitor) {
         4     // 刷新前准备工作,包括设置启动时间,是否激活标识位,初始化属性源(property source)配置
         5     prepareRefresh();
         6 
         7     // 创建beanFactory(过程是根据xml为每个bean生成BeanDefinition并注册到生成的beanFactory
         8     ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
         9 
        10     //准备创建好的beanFactory(给beanFactory设置ClassLoader,设置SpEL表达式解析器,设置类型转化器【能将xml String类型转成相应对象】,
        11     //增加内置ApplicationContextAwareProcessor对象,忽略各种Aware对象,注册各种内置的对账对象【BeanFactory,ApplicationContext】等,
        12     //注册AOP相关的一些东西,注册环境相关的一些bean
        13     prepareBeanFactory(beanFactory);
        14 
        15     try {
        16       // 模板方法,为容器某些子类扩展功能所用(工厂后处理器)这里可以参考BeanFactoryPostProcessor接口的postProcessBeanFactory方法
        17       postProcessBeanFactory(beanFactory);
        18 
        19       // 调用所有BeanFactoryPostProcessor注册为Bean
        20       invokeBeanFactoryPostProcessors(beanFactory);
        21 
        22       // 注册所有实现了BeanPostProcessor接口的Bean
        23       registerBeanPostProcessors(beanFactory);
        24 
        25       // 初始化MessageSource,和国际化相关
        26       initMessageSource();
        27 
        28       // 初始化容器事件传播器
        29       initApplicationEventMulticaster();
        30 
        31       // 调用容器子类某些特殊Bean的初始化,模板方法
        32       onRefresh();
        33 
        34       // 为事件传播器注册监听器
        35       registerListeners();
        36 
        37       // 初始化所有剩余的bean(普通bean)
        38       finishBeanFactoryInitialization(beanFactory);
        39 
        40       // 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
        41       finishRefresh();
        42     }
        43     catch (BeansException ex) {
        44       if (logger.isWarnEnabled()) {
        45         logger.warn("Exception encountered during context initialization - " +
        46             "cancelling refresh attempt: " + ex);
        47       }
        48       // 销毁已创建的bean
        49       destroyBeans();
        50       // 重置`active`标志
        51       cancelRefresh(ex);
        52       throw ex;
        53     }
        54     finally {
        55               //重置一些缓存
        56       resetCommonCaches();
        57     }
        58   }
        59 }
        refresh()
      3. 在这里我想说一下,这个refresh()方法其实是一个模板方法, 很多方法都让不同的实现类去实现,但该类本身也实现了其中一些方法,并且这些已经实现的方法是不允许子类重写的,比如:prepareRefresh()方法。
      4.  1 protected void prepareRefresh() {
         2   this.startupDate = System.currentTimeMillis();//设置容器启动时间
         3   this.closed.set(false);//容器关闭标志,是否关闭?
         4   this.active.set(true);//容器激活标志,是否激活?
         5   
         6   if (logger.isInfoEnabled()) {//运行到这里,控制台就会打印当前容器的信息
         7     logger.info("Refreshing " + this);
         8   }
         9 
        10   // 空方法,由子类覆盖实现,初始化容器上下文中的property文件
        11   initPropertySources();
        12 
        13   //验证标记为必需的所有属性均可解析,请参阅ConfigurablePropertyResolver#setRequiredProperties
        14   getEnvironment().validateRequiredProperties();
        15 
        16   //允许收集早期的ApplicationEvents,一旦多播器可用,即可发布...
        17   this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
        18 }
        prepareRefresh()
    4. invokeBeanFactoryPostProcessors.invokeBeanDefinitionRegistryPostProcessors 注册bean
    5. postProcessor.postProcesBeanDefinitionRegistry(registry),内部方法,解析日常注解
    6. processConfigurationClass.componentScanParser  将带有@bean注解的类进行registry
    7. componentScanParser.parse,结尾的scanner.doScan,扫描basepackages,并将扫描到的bean生成一个个BeanDefinitionHolder;并执行后续的registerBeanDefinition,将其添加到beanFactory
    8. registry.registerBeanDefinition,将扫描到的bean存放到一个beanname为key、beanDefinition为value的map内
    9. getBean => getBeanFactory.getBean => doGetBean
      doCreateBean => createBeanInstance => autowireConstructor => autowireConstructor => instantiate => instantiateClass => newInstance

      1. AbstractBeanFactory
    10. 属性注入 doCreateBean方法,填充Bean(populateBean)

      借鉴:https://segmentfault.com/a/1190000012887776#articleHeader5

    各位看官大佬,不足之处,多多批评指正,不胜感激!
  • 相关阅读:
    导出表结构语句
    closeChannel: close the connection to remote address[] result: true
    spingboot使用rabbitmq
    服务器很卡问题排查
    docker-compose安装nginx
    Docker方式安装ShowDoc
    "docker build" requires exactly 1 argument
    Intellij IDEA常用快捷键介绍 Intellij IDEA快捷键大全汇总
    IDEA 2018 3.4 激活破解方法
    jpress:v3.2.5的docker-compose安装
  • 原文地址:https://www.cnblogs.com/guoguochong/p/15491546.html
Copyright © 2020-2023  润新知