SpringBoot源码分析系列之二:启动原理分析

简介: 我们都知道SpringBoot是目前微服务比较流行的技术选型,它可以将工程打成war包的方式在tomcat进行启动,也可以打成jar包,直接对外提供服务。那我们就会好奇,它是怎么去启动服务的,同时是怎么去加载前端页面、js文件、配置文件以及class文件等等然后向外提供web服务的。带着一系列的疑问,一步步探究SpringBoot的启动原理。SpringBoot大致启动流程源码跟踪分析总结

引言

我们都知道SpringBoot是目前微服务比较流行的技术选型,它可以将工程打成war包的方式在tomcat进行启动,也可以打成jar包,直接对外提供服务。那我们就会好奇,它是怎么去启动服务的,同时是怎么去加载前端页面、js文件、配置文件以及class文件等等然后向外提供web服务的。带着一系列的疑问,一步步探究SpringBoot的启动原理。

  • SpringBoot大致启动流程
  • 源码跟踪分析
  • 总结

1.SpringBoot大致启动流程如下图所示。

3.png

2.源码跟踪分析

(1)main函数为主程序入口,SpringApplication调用run方法来启动SpringBoot服务。注解的含义在上一篇文章中进行了说明,这里不再赘述。

@SpringBootApplication(scanBasePackages = {"com.hikvision.center"})
@MapperScan("com.hikvision.center.module.mapper")
@ImportResource(locations = {"classpath:springMVC-servlet.xml"})
@ServletComponentScan
public class WebApplication extends SpringBootServletInitializer{
  static Logger logger = LoggerFactory.getLogger(WebApplication.class);
  public static void main(String[] args) {
          //程序入口
      SpringApplication.run(WebApplication.class, args);
  }
}

(2)run方法是一个静态方法,主要执行一系列的初始化加载操作。

 //
public static ConfigurableApplicationContext run(Object source, String... args) {
  return run(new Object[] { source }, args);
}

(3)ConfigurableApplicationContext表示该 Context 是可修改的,也就是在构建 Context中用户可以动态添加或修改已有的配置信息。下图为ApplicationContext类关系图。

image.png

//创建了SpringApplication实例,同时调用run方法
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
  return new SpringApplication(sources).run(args);
}

(4)初始化操作。

//SpringApplication构造函数中,进行初始化操作,上下文从指定的源中加载bean,实例可以在被调用前进行自定义
public SpringApplication(Object... sources) {
    initialize(sources);
  }

(5)主要是为SpringApplication对象赋一些初值。

@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
  if (sources != null && sources.length > 0) {
    this.sources.addAll(Arrays.asList(sources));
  }
  //判断当前允许的环境是否为web环境
  this.webEnvironment = deduceWebEnvironment();
  //
  setInitializers((Collection) getSpringFactoriesInstances(
      ApplicationContextInitializer.class));
  //
  setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  //
  this.mainApplicationClass = deduceMainApplicationClass();
}

(6)回到run方法中去看具体的实现,该方法主要完成ApplicationContext配置加载。

public ConfigurableApplicationContext run(String... args) {
  //性能检查,查看代码的运行时间
  StopWatch stopWatch = new StopWatch();
  stopWatch.start();
  //设置上下文ID,设置父应用上下文,添加监听器和刷新容器相关的操作等
  ConfigurableApplicationContext context = null;
  //异常分析器
  FailureAnalyzers analyzers = null;
  //设置java.awt.headless属性,
  configureHeadlessProperty();
  //创建应用监听器SpringApplicationRunListeners同时开始监听
  SpringApplicationRunListeners listeners = getRunListeners(args);
  //启动监听器
  listeners.started();
  try {
    //获取启动参数
    ApplicationArguments applicationArguments = new DefaultApplicationArguments(
        args);
    //加下SpringBoot配置环境
    ConfigurableEnvironment environment = prepareEnvironment(listeners,
        applicationArguments);
    //定义输出的标志,打印spring
    Banner printedBanner = printBanner(environment);
    //创建应用上下文
    context = createApplicationContext();
    //注册异常分析器
    analyzers = new FailureAnalyzers(context);
    //为ApplicationContext加载environment,初始化IoC容器,调用SpringApplicationRunListener的contextLoaded()方法,完成IOC容器加载
    prepareContext(context, environment, listeners, applicationArguments,
        printedBanner);
    //初始化自动配置
    refreshContext(context);
    //SpringBoot完成ApplicationContext初始化
    afterRefresh(context, applicationArguments);
    //广播已经完成初始化全部过程
    listeners.finished(context, null);
    //关闭任务执行还见监听器
    stopWatch.stop();
    if (this.logStartupInfo) {
      new StartupInfoLogger(this.mainApplicationClass)
          .logStarted(getApplicationLog(), stopWatch);
    }
    return context;
  }
  catch (Throwable ex) {
    handleRunFailure(context, listeners, analyzers, ex);
    throw new IllegalStateException(ex);
  }
}

3.总结

从以上Springboot启动过程来看,它主要创建了程序配置环境(environment)、事件监听(listeners)、应用上下文(applicationContext),并在以上基础上,在容器中开始加载和实例化我们需要的Bean,在这些过程中有些过程是可以自定义的。


相关文章
|
3月前
|
安全 NoSQL Java
SpringBoot接口安全:限流、重放攻击、签名机制分析
本文介绍如何在Spring Boot中实现API安全机制,涵盖签名验证、防重放攻击和限流三大核心。通过自定义注解与拦截器,结合Redis,构建轻量级、可扩展的安全防护方案,适用于B2B接口与系统集成。
519 3
|
3月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
|
5月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
893 0
|
2月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
286 5
|
2月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
371 2
|
5月前
|
前端开发 Java 数据库连接
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
SpringBoot参数校验底层原理和实操。深度历险、深度解析(图解+秒懂+史上最全)
|
4月前
|
JavaScript Java 应用服务中间件
基于springboot的学生成绩分析和弱项辅助系统
本系统旨在解决学生成绩分析与弱项辅助信息管理效率低下的问题,通过软件技术实现数据处理的高效化、流程化与规范化,提升管理质量与便捷性。
|
5月前
|
XML 人工智能 IDE
Springboot整合SSMP报错分析
本文介绍了Springboot整合SSMP框架时常见的报错及解决方案,包括MyBatis-Plus版本不兼容导致的Lambda表达式条件构造器报错及表名不匹配问题。通过升级或降级MyBatis-Plus版本、使用@TableName注解或配置table-prefix属性,可有效解决上述问题,帮助开发者避免在整合SSMP时出现不必要的错误。
270 0
|
9月前
|
Java Spring
SpringBoot自动配置原理
本文深入解析了SpringBoot的核心功能——自动配置,重点探讨了`org.springframework.boot.autoconfigure`及相关注解的工作机制。通过分析`@SpringBootApplication`、`@EnableAutoConfiguration`等注解,揭示了SpringBoot如何基于类路径和条件自动装配Bean
450 8
|
9月前
|
Java
SpringBoot自动装配的原理
在SpringBoot项目的启动引导类上都有一个注解@SpringBootApplication 这个注解是一个复合注解, 其中有三个注解构成 , 分别是 ● @SpringBootConfiguration : 是@Configuration的派生注解 , 标注当前类是一个SpringBoot的配置类 ● @ComponentScan : 开启组件扫描, 默认扫描的是当前启动引导了所在包以及子包 ● @EnableAutoConfiguration : 开启自动配置(自动配置核心注解) 2.在@EnableAutoConfiguration注解的内容使用@Import注解导入了一个AutoC