SpringBoot之Refresh流程的简单说明

 更新时间:2023年09月16日 08:51:24   作者:之诚  
这篇文章主要介绍了SpringBoot之Refresh流程的简单说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

启动入口

在这里插入图片描述

Springboot 程序的启动入口是一个main方法,从这个入口方法一路追溯下去,最终可以找到Refresh方法的。

追溯流程如下:

org.springframework.boot.SpringApplication#run(java.lang.Class<?>, java.lang.String...)
org.springframework.boot.SpringApplication#run(java.lang.Class<?>[], java.lang.String[])
org.springframework.boot.SpringApplication#run(java.lang.String...)
org.springframework.boot.SpringApplication#refreshContext
org.springframework.boot.SpringApplication#refresh(org.springframework.context.ConfigurableApplicationContext)
org.springframework.context.ConfigurableApplicationContext#refresh

上面的几个方法就是从main到refresh方法的路径,中间省略了一两个方法。用心找下就能追溯到refresh。

查看源码的时候一定要抓住主路径,放弃次要路径,因为Spring框架台复杂庞大了,不可能弄清楚所有的细节的。

Refresh方法

最终追溯到的refresh方法也是 ConfigurableApplicationContext 接口的方法, 这个接口有三个很重要的实现类, 我们先看下 AbstractApplicationContext 类中的refresh方法。

在这里插入图片描述

图中是否有一种熟悉的感觉, 这个方法就是众多的讲Spring的博客文章都必定会说到的方法, 里面的每个步骤都是很重要的。

  • prepareBeanFactory: 构建上下文, 注册各个框架的BeanPostProcesser和BeanFactoryPostProcessor的实现类。 注意是框架的。 还会设置忽略一些依赖比如各个Aware的依赖, 这个是为了注入其他的依赖的接口,所以不能用来注入依赖。 同时还会设置注册依赖BeanFactory等的依赖。
  • ObtainFreshBeanFactory: 创建容器DefaultListableBeanFactory, 接着扫描classpath路径下的所有的Bean信息,并生成对应的BeanDefinition。
  • prepareBeanfactory: 一些框架依赖的beanFactoryPostProcessor在这里加载进容器; 对于SPEL表达式在这里替换; 一些BeanPostProcessor在这里注入; Environment类的注入容器 ; BeanFactory也把自己放入容器中。
  • postProcessBeanFactory 这个方法是个空实现,但是web模块中使用这个注入web的一些特有的ServletContextAwareProcessor实现类
  • invokeBeanFactoryPostProcessors 方法,调用所有的BeanFactoryPostProcessors实现类的的postProcessBeanFactory方法; 会先调用可排序BeanFactoryPostProcessors实现类, 在调用没有排序的postProcessBeanFactory实现类。 这里会先实例BeanFactoryPostProcessors的实现类,但是内部的依赖还不会注入进去, 所以在postProcessBeanFactory方法的逻辑中不要直接使用spring的依赖类。
  • registerBeanPostProcessors 注册BeanPostProcessor的实现类了。 这里会从容器中获取所有的BeanPostProcessor的BeanDefinition , 并初始化后放(会注入依赖的)入到容器中。
  • initMessageSource初始化国际化的资源信息放入容器中
  • initApplicationEventMulticaster 初始化spring的消息监听器。

这里会先检查容器中用户有没有实现自己的事件监听器,如果有的话就使用用户自定义的, 如果没有就使用Spring自带的简单的事件监听器SimpleApplicationEventMulticaster。

这里监听器会 registerSingleton方法简单的注册到容器AbstractApplicationContext实现 ApplicationEventPublisher接口(中间继承间隔好几层),而这个接口就有发布时间的方法。

所以一般的容器都有发布事件的能力。发布事件的逻辑是, publishEvent方法内部调用SimpleApplicationEventMulticaster的* onApplicationEvent方法, 这个方法内部会先从容器中获取所有的事件监听器Bean,并放入缓存中。

然后在根据事件的类型选择正确的事件处理器来处理, 这里会使用线程池来处理

  • onRefresh这个方法 AbstractApplicationContext中是空实现, 我们看下 ServletWebServerApplicationContext中的实现。 在这个子类中,这个方法被用来 初始化WebServer, 并启动服务。 tomcat就是在这里启动
  • registerListeners注册事件监听器, 这里会把容器中的所有事件监听器类都注册到SimpleApplicationEventMulticaster中。 并把在启动这步之前积攒的事件消息都遍历发布出去。
  • finishBeanFactoryInitialization完成容器初始化完成后的收尾方法。 这里会往容器中注入很多的类型转换的bean。 并在这里实例化所有没有设置lazy- init的
  • finishRefresh整个启动过程的最后的方法, 这里会清空一些只在启动中有用的缓存信息,发布启动成功的事件。

在第五步的invokeBeanFactoryPostProcessors方法中, 除了会调BeanFactoryPostProcessors的实现类方法外还会调调用BeanDefinitionRegistryPostProcessor 类的postProcessBeanDefinitionRegistry方法,很多的框架就是通过这个方法来注入自己的bean, 比如Mybatis的 org.mybatis.spring.mapper.MapperScannerConfigurer 类。

总结

Refresh 是Spring启动的重要方法, Spring的启动整个周期都在这个方法中有提现,上面的描述只是我自己的理解,不一定准确完善。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java Lombok之@Accessors用法及说明

    java Lombok之@Accessors用法及说明

    这篇文章主要介绍了java Lombok之@Accessors用法及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Java版数据结构插入数据时遇到的结点为空的问题详解

    Java版数据结构插入数据时遇到的结点为空的问题详解

    这篇文章主要介绍了Java版数据结构插入数据时遇到的结点为空的问题及解决办法,需要的朋友们可以学习下。
    2019-09-09
  • java isInterrupted()判断线程的实例讲解

    java isInterrupted()判断线程的实例讲解

    在本篇内容里小编给大家分享的是一篇关于java isInterrupted()判断线程的实例讲解内容,有兴趣的朋友们可以学习下。
    2021-05-05
  • springboot mybatis手动事务的实现

    springboot mybatis手动事务的实现

    本文主要介绍了springboot mybatis手动事务的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-12-12
  • Java 创建两个线程模拟对话并交替输出实现解析

    Java 创建两个线程模拟对话并交替输出实现解析

    这篇文章主要介绍了Java 创建两个线程模拟对话并交替输出实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • 详解Java 类的加载、连接和初始化

    详解Java 类的加载、连接和初始化

    这篇文章主要介绍了Java 类的加载、连接和初始化的的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • Java多线程实例

    Java多线程实例

    本文给大家介绍java多线程实例,对java多线程知识感兴趣的朋友参考下吧
    2015-11-11
  • 详解Java的设计模式编程中的原型模式

    详解Java的设计模式编程中的原型模式

    这篇文章主要介绍了Java的设计模式编程中的原型模式,处理对象复制时要特别注意浅拷贝和深拷贝的问题,需要的朋友可以参考下
    2016-02-02
  • 如何通过java实现highcharts导出图片至excel

    如何通过java实现highcharts导出图片至excel

    这篇文章主要介绍了如何通过java实现highcharts导出图片至excel。文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面我们就来一起学习一下吧
    2019-06-06
  • Java数组的遍历与求和知识点

    Java数组的遍历与求和知识点

    本篇文章给大家总计了Java数组的遍历与求和的知识点以及需要注意的地方,需要的朋友参考学习下。
    2018-02-02

最新评论