SpringBoot实践(三十):了解SpringBoot的启动过程

发布于:2023-01-19 ⋅ 阅读:(318) ⋅ 点赞:(0)

目录

SpringBootApplication注解

@EnableAutoConfiguration注解

@AutoConfigurationPackage注解

@ComponentScan注解

 SpringBoot启动过程

构建服务

创建环境

创建容器

填充容器


纵览springboot启动过程会发现,其本质是创建1个IOC容器,也就是存放bean的容器,使用自动装配简化了spring的各种bean配置(xml文件),启动的所有过程都是为了构建这个bean容器服务。本来首先分析启动类上的注解,再分析SpringApplication的构建过程和run方法流程。

SpringBootApplication注解

启动类上的@SpringBootApplication注解是组合注解:

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

由三个注解组成: 

@SpringBootConfiguration: 本质上是@Configuration注解,@Configuration等价于<Beans></Beans>,其中如果有@Bean注解其等价于<Bean></Bean>,这里加@Configuration注解表明这个启动类就是个配置类;

@EnableAutoConfiguration :扫描spring.factories文件,自动配置;

@ComponentScan: 告诉Spring 哪个packages 的用注解标识的类会被spring自动扫描并且装入bean容器,这里会排除spring.factories文件的value;

重点关注的是@EnableAutoConfiguration和@ComponentScan注解

@EnableAutoConfiguration注解

它也是一个组合注解,首先关注@Import(AutoConfigurationImportSelector)这个注解,@Import这个注解类是用于导入配置类可以理解java程序中的Import 包和类;比如我们可以使用@Import(test.class)来把test.class放到bean容器,这里导入AutoConfigurationImportSelector有什么用呢;

AutoConfigurationImportSelector是一个接口,其有一个方法getAutoConfigurationEntry(),

该方法读取spring.factories中的所有配置类列表(也包括依赖包里面的META-INF下的配置文件spring.factories)

 最终@EnableAutoConfiguration注解实现的作用就是META-INF/spring.factories配置文件的value进行排序过滤后返回;

@AutoConfigurationPackage注解

@EnableAutoConfiguration还有个@AutoConfigurationPackage注解是做什么用的,其实就是个包路径,也就是作用范围的指定。将添加该注解的类所在的package 作为 自动配置package 进行管理,@Import(AutoConfigurationPackages.Registrar)表示对于使用了该注解的类所在的包,应当使用AutoConfigurationPackages注册。

 注册类和方法如下:自动扫描同级及以下的包,如果有包在@AutoConfigurationPackage注解范围以上扫描不到。

@ComponentScan注解

@ComponentScan用于类或接口上主要是指定扫描路径,spring会把指定路径下带有指定注解的类注册到IOC容器中。会被自动装配的注解包括@Controller、@Service、@Component、@Repository等等。@EnableAutoConfiguration注解实现了spring.factories中配置类的自动配置,@ComponentScan实现了用户指定的类的自动注入;如果不设置的话默认扫描@ComponentScan注解所在类的同级类和同级目录下的所有类,所以对于一个Spring Boot项目,一般会把入口类放在顶层目录中,这样就能够保证源码目录下的所有类都能够被扫描到;

 SpringBoot启动过程

上面说了springboot的启动流程本质上创建IOC容器,从实现上分为两步:创建SpringApplication对象和调用run方法;从功能上看可以分为4步:构建服务、创建环境、创建容器、填充容器;

构建服务:就是new SpringApplication对象的过程,期间会推断web应用类型,从spring.factories中获取初始化器和监听器;

创建环境:environment创建过程读取很多的资源信息和配置;

创建容器:这里的容器就是Context上下文也是bean工厂;

填充容器:填充容器就是refresh后的过程;

构建服务

上面说了构建服务就是创建 SpringApplication对象,做了以下几个事情:

  • 保存一些信息。
  • 判定当前应用的类型。ClassUtils。Servlet
  • bootstrappers:初始启动引导器(List<Bootstrapper>):去spring.factories文件中找 org.springframework.boot.Bootstrapper
  • 找 ApplicationContextInitializer;去spring.factories找 ApplicationContextInitializer,得到List<ApplicationContextInitializer<?>> initializers
  • 找 ApplicationListener ;应用监听器。去spring.factories找 ApplicationListener,得到List<ApplicationListener<?>> listeners

创建环境

上一步完成后,就到了run方法了,后面的几个都是run方法后的过程:

  • StopWatch,记录应用的启动时间
  • 创建引导上下文(Context环境)createBootstrapContext(),获取到所有之前的 bootstrappers 挨个执行 intitialize() 来完成对引导启动器上下文环境设置
  • 让当前应用进入headless模式。java.awt.headless;
  • 获取所有 RunListener(运行监听器)【为了方便所有Listener进行事件感知】,getSpringFactoriesInstances 去spring.factories找 SpringApplicationRunListener.
  • 遍历 SpringApplicationRunListener 调用 starting 方法,相当于通知所有感兴趣系统正在启动过程的人,项目正在 starting。
  • 保存命令行参数;ApplicationArguments
  • 准备环境 prepareEnvironment():返回或者创建基础环境信息对象,StandardServletEnvironment,配置环境信息对象,读取所有的配置源的配置属性值,绑定环境信息,监听器调用 listener.environmentPrepared();通知所有的监听器当前环境准备完成;

创建容器

这一步就是要1个创建IOC容器createApplicationContext对象,

  • 根据项目类型(Servlet)创建容器,当前会创建AnnotationConfigServletWebServerApplicationContext
  • 准备ApplicationContext IOC容器的基本信息 prepareContext():保存环境信息;IOC容器的后置处理流程;应用初始化器applyInitializers;遍历所有的 ApplicationContextInitializer ,调用 initialize来对ioc容器进行初始化扩展功能;遍历所有的 listener调用 contextPrepared。EventPublishRunListenr通知所有的监听器contextPrepared;所有的监听器 调用 contextLoaded;通知所有的监听器contextLoaded;

填充容器

  • 刷新IOC容器(refreshContext):创建容器中的所有组件(Spring注解)
  • 容器刷新完成后工作(afterRefresh):所有监听器调用 listeners.started(context); 通知所有的监听器 started;调用所有runners的callRunners()获取容器中的 ApplicationRunner;获取容器中的 CommandLineRunner;合并所有runner并且按照@Order进行排序;遍历所有的runner。调用 run 方法;如果以上有异常调用Listener 的 failed;

springboot启动流程:https://www.yuque.com/atguigu/springboot/tmvr0e
springboot启动流程b站:https://www.bilibili.com/video/BV1e14y1A7pT/?vd_source=837a80ccc382967b7ab909f9407a02a4#reply143642551168


网站公告

今日签到

点亮在社区的每一天
去签到