当前位置: 首页 > news >正文

Spring Boot启动流程

1. 启动类与main方法

  • 入口点:Spring Boot应用通常有一个带有@SpringBootApplication注解的主类,并包含一个public static void main(String[] args)方法。
    • @SpringBootApplication是一个组合注解,包含了:
      • @Configuration: 标记该类为配置类。
      • @EnableAutoConfiguration: 自动根据classpath中的依赖进行配置。
      • @ComponentScan: 自动扫描指定包及其子包下的组件(如@Component@Service@Repository@Controller等)。
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

2. 创建SpringApplication实例

  • 构造函数
    • 推断应用类型:检查classpath中是否存在特定的类(如Servlet、Reactive相关的类),以确定是Servlet还是Reactive应用。
    • 加载初始器和监听器:从META-INF/spring.factories文件中加载默认的ApplicationContextInitializerApplicationListener

3. SpringApplication.run() 方法执行

环境准备
  • 创建并配置Environment:基于命令行参数、系统属性、环境变量等初始化Environment对象。
    • 可以通过--spring.config.locationSPRING_CONFIG_LOCATION环境变量指定外部配置文件的位置。
  • 触发事件:发布ApplicationEnvironmentPreparedEvent事件,允许外部工具或开发者自定义环境设置。
    • 可以通过实现ApplicationListener<ApplicationEnvironmentPreparedEvent>来自定义逻辑。
打印Banner
  • 如果启用了banner,则显示项目启动的图形化标识。
    • 可以通过设置spring.main.banner-modeoff来关闭banner。
创建ApplicationContext
  • 根据应用类型选择合适的ApplicationContext实现(例如,对于Web应用通常是AnnotationConfigServletWebServerApplicationContext)。
    • 对于非Web应用,可能是AnnotationConfigApplicationContext
加载Sources
  • 将所有指定的source(通常是带有@Configuration注解的类)注册到ApplicationContext中。
    • 这包括了自动扫描到的组件和显式声明的配置类。
刷新上下文前的准备工作
  • 触发ApplicationContextInitializedEvent事件。
  • 调用所有的ApplicationContextInitializer进行额外的配置。
    • 这些initializer可以在刷新之前对context进行进一步的定制。

4. ApplicationContext刷新过程

BeanFactory准备
  • 设置bean工厂的各种属性,包括转换服务、属性编辑器等。
    • 配置了诸如PropertyEditorRegistrar等用于处理属性值转换的机制。
BeanDefinition加载
  • 扫描classpath:寻找带有@Component@Service@Repository@Controller等注解的类,并将其注册为bean definitions。
    • 使用ClassPathScanningCandidateComponentProvider扫描指定包下的组件。
    • 条件注解(如@ConditionalOnClass@ConditionalOnMissingBean等)确保仅在满足特定条件时才生效。
自动配置
  • 自动配置机制:通过@EnableAutoConfiguration触发自动配置过程。它会根据classpath中的依赖自动配置相应的beans。
    • 自动配置类位于spring-boot-autoconfigure模块中,它们通过spring.factories文件被发现并加载。
    • 每个自动配置类都可能有条件注解,确保仅在满足特定条件时才生效。
BeanFactoryPostProcessor执行
  • 处理各种后处理器,如PropertySourcesPlaceholderConfigurer用于解析占位符。
    • 解析${...}形式的属性值,替换为实际值。
Bean实例化
  • 根据bean definitions实例化单例bean,并进行依赖注入。
    • 初始化bean时,可能还会执行一些生命周期回调方法,如@PostConstruct标注的方法。
    • 如果需要AOP代理,则在此阶段生成代理对象。

5. 刷新完成后的工作

  • 触发ContextRefreshedEvent:表示ApplicationContext已完全刷新。
  • 执行CommandLineRunner/ApplicationRunner beans:如果有任何实现了CommandLineRunnerApplicationRunner接口的beans,它们的方法会被调用。
    • 这些runner可以用来执行最后的初始化操作。

6. 应用就绪

  • 触发ApplicationReadyEvent:表示应用已经准备好接收请求或执行预定的任务。
  • 开启web服务器:如果是Web应用,此时嵌入式的Tomcat服务器将会启动,并开始监听HTTP请求。

7. 错误处理

  • 错误处理机制:Spring Boot提供了强大的错误处理机制,包括但不限于自定义错误页面、全局异常处理器等,以增强应用的健壮性。
    • 可以通过实现ErrorController来自定义错误页面。
    • 使用@ControllerAdvice@ExceptionHandler来处理全局异常。

额外细节

  • 外部化配置:支持多种方式的外部化配置,如命令行参数、环境变量、properties/yaml文件等。

    • 可以通过application.propertiesapplication.yml文件进行配置。
    • 支持使用@Value注解直接注入配置值。
    • 可以通过spring.profiles.active指定激活的profile,从而加载不同的配置。
  • 健康检查和度量:通过Actuator模块提供的端点,可以监控应用的健康状况和性能指标。

    • 提供了诸如/actuator/health/actuator/metrics等端点。
    • 可以自定义健康指示器(Health Indicator)来扩展健康检查功能。
  • 日志配置:Spring Boot默认支持多种日志框架,并可以通过简单的配置定制日志级别和输出格式。

    • 支持Logback、Log4j2等日志框架,默认使用Logback。
    • 可以通过logging.level.*=DEBUG等配置项调整日志级别。

关键技术细节

  • 条件注解:如@ConditionalOnClass@ConditionalOnMissingBean等,使得Spring Boot能够根据当前环境动态地启用或禁用某些配置。
  • 事件驱动模型:Spring Boot在整个启动过程中使用了大量的事件发布和监听机制,这使得开发者可以在应用启动的不同阶段插入自定义逻辑。
    • 例如,可以通过实现ApplicationListener<ApplicationStartedEvent>来自定义启动逻辑。

示例代码片段

以下是一个更完整的示例,展示了如何使用Spring Boot的基本结构,并结合了一些高级特性和配置:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(DemoApplication.class);
        // 关闭banner
        app.setBannerMode(Banner.Mode.OFF);
        // 添加自定义的ApplicationContextInitializer
        app.addInitializers(new MyCustomApplicationContextInitializer());
        app.run(args);
    }
}

@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("MyCommandLineRunner executed");
    }
}

@Configuration
public class MyCustomConfig {
    @Bean
    @ConditionalOnMissingBean(name = "customBean")
    public String customBean() {
        return "This is a custom bean";
    }
}

// 自定义健康检查
@Component
public class CustomHealthIndicator extends AbstractHealthIndicator {
    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        builder.up().withDetail("custom", "Everything is OK!");
    }
}

// 全局异常处理器
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<Object> exception(Exception exception) {
        return new ResponseEntity<>("An error occurred: " + exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

// 自定义ApplicationContextInitializer
public class MyCustomApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        // 自定义环境配置
        Map<String, Object> map = new HashMap<>();
        map.put("my.custom.property", "customValue");
        environment.getPropertySources().addFirst(new MapPropertySource("customProperties", map));
    }
}

相关文章:

  • 力扣每日一题:2712——使所有字符相等的最小成本
  • 车载以太网网络测试-26【SOME/IP-通信方式-2】
  • 【力扣hot100题】(026)合并两个有序链表
  • [RoarCTF 2019]Easy Java1
  • 排序算法可视化工具——基于React的交互式应用
  • openEuler 24.03 (LTS) 安装 docker 记录
  • Go语言从零构建SQL数据库引擎(3)
  • rustdesk 客户端使用
  • 算法篇-------------双指针法
  • Matplotlib绘制常用图像
  • 各种网址整理-vue,前端,linux,ai前端开发,各种开发能用到的网址和一些有用的博客
  • javaweb自用笔记:文件上传案例、登录(统一拦截)案例
  • SpringCould微服务架构之Docker(9)
  • 便捷解析下载热门短视频、图片的安卓免费软件
  • 代码随想录C++算法训练,二叉树(day16)
  • vcpkg安装及使用教程,以安装matio库解析mat文件为例
  • 部署Dify接入微信验证反代根目录创建一个文件通过微信小程序验证
  • 机器学习入门指南:从零开始理解AI的核心
  • 高效屏幕录制软件,涵盖多样功能满足多元需求
  • k8s node cpu打满会导致容器发生什么?
  • 建立问答类的网站/seo代理
  • 网站备案的影响/广告公司网站制作
  • 做网络平台的网站有哪些/武汉seo网站排名优化公司
  • 阿里云服务的官方网站/广州网站快速优化排名
  • 晋江网站建设公司哪家好/发免费广告电话号码
  • 网站app免费软件/百度云搜索引擎入口百度网盘