当前位置: 代码网 > it编程>编程语言>Java > SpringBoot应用启动机制的使用详解

SpringBoot应用启动机制的使用详解

2025年10月11日 Java 我要评论
idea中启动springboot的过程1. 预启动阶段1.1 环境检测与验证// idea 执行的前置检查- jdk 版本兼容性验证- 项目依赖完整性检查- spring boot 版本与插件匹配-

idea中启动springboot的过程

1. 预启动阶段

1.1 环境检测与验证

// idea 执行的前置检查

  • - jdk 版本兼容性验证
  • - 项目依赖完整性检查
  • - spring boot 版本与插件匹配
  • - 构建工具配置验证(maven/gradle)
  • - 应用配置文件语法检查

1.2 类路径构建

类路径组成:

├── 项目编译输出目录 (target/classes 或 build/classes)
├── 依赖库 (maven: ~/.m2/repository, gradle: ~/.gradle/caches)
├── 资源文件 (src/main/resources)
├── 测试资源文件 (src/test/resources) [测试时]
└── idea 特定模块路径

2. spring boot 应用启动核心流程

2.1 springapplication 初始化阶段

public class springapplication {
    
    public springapplication(class<?>... primarysources) {
        // 1. 主配置类存储
        this.primarysources = new linkedhashset<>(arrays.aslist(primarysources));
        
        // 2. 推断应用类型
        this.webapplicationtype = webapplicationtype.deducefromclasspath();
        
        // 3. 加载 applicationcontextinitializer
        setinitializers(getspringfactoriesinstances(
            applicationcontextinitializer.class));
        
        // 4. 加载 applicationlistener
        setlisteners(getspringfactoriesinstances(applicationlistener.class));
        
        // 5. 推断主应用类
        this.mainapplicationclass = deducemainapplicationclass();
    }
}

2.2 运行阶段详细分解

public configurableapplicationcontext run(string... args) {
    // 阶段 1: 启动准备
    stopwatch stopwatch = new stopwatch();
    stopwatch.start();
    
    // 阶段 2: 监听器通知 - applicationstartingevent
    springapplicationrunlisteners listeners = getrunlisteners(args);
    listeners.starting();
    
    try {
        // 阶段 3: 环境准备
        applicationarguments applicationarguments = 
            new defaultapplicationarguments(args);
        configurableenvironment environment = prepareenvironment(listeners, applicationarguments);
        
        // 阶段 4: 配置忽略的 bean 信息
        configureignorebeaninfo(environment);
        
        // 阶段 5: 打印 banner
        banner printedbanner = printbanner(environment);
        
        // 阶段 6: 创建应用上下文
        context = createapplicationcontext();
        context.setapplicationstartup(this.applicationstartup);
        
        // 阶段 7: 准备上下文
        preparecontext(context, environment, listeners, 
                      applicationarguments, printedbanner);
        
        // 阶段 8: 刷新上下文(核心)
        refreshcontext(context);
        
        // 阶段 9: 刷新后处理
        afterrefresh(context, applicationarguments);
        
        // 阶段 10: 启动完成通知
        stopwatch.stop();
        if (this.logstartupinfo) {
            new startupinfologger(this.mainapplicationclass)
                .logstarted(getapplicationlog(), stopwatch);
        }
        
        // 阶段 11: 发布 applicationreadyevent
        listeners.started(context);
        
        // 阶段 12: 执行 runner bean
        callrunners(context, applicationarguments);
        
        // 阶段 13: 发布 applicationstartedevent
        listeners.ready(context, stopwatch);
        
    } catch (throwable ex) {
        handlerunfailure(context, listeners, ex);
        throw new illegalstateexception(ex);
    }
    
    return context;
}

3. 上下文刷新详细过程

3.1 beanfactory 初始化流程

// abstractapplicationcontext.refresh() 完整流程
@override
public void refresh() throws beansexception, illegalstateexception {
    synchronized (this.startupshutdownmonitor) {
        startupstep contextrefresh = this.applicationstartup.start("spring.context.refresh");
        
        // 步骤 1: 准备刷新 - 设置启动日期、激活状态等
        preparerefresh();
        
        // 步骤 2: 获取新的 beanfactory
        configurablelistablebeanfactory beanfactory = obtainfreshbeanfactory();
        
        // 步骤 3: 准备 beanfactory 使用
        preparebeanfactory(beanfactory);
        
        try {
            // 步骤 4: 允许 beanfactory 后处理
            postprocessbeanfactory(beanfactory);
            
            startupstep beanpostprocess = this.applicationstartup.start("spring.context.beans.post-process");
            
            // 步骤 5: 调用 beanfactorypostprocessor
            invokebeanfactorypostprocessors(beanfactory);
            
            // 步骤 6: 注册 beanpostprocessor
            registerbeanpostprocessors(beanfactory);
            beanpostprocess.end();
            
            // 步骤 7: 初始化消息源
            initmessagesource();
            
            // 步骤 8: 初始化事件广播器
            initapplicationeventmulticaster();
            
            // 步骤 9: 初始化特殊 bean(模板方法)
            onrefresh();
            
            // 步骤 10: 注册监听器
            registerlisteners();
            
            // 步骤 11: 完成 beanfactory 初始化
            finishbeanfactoryinitialization(beanfactory);
            
            // 步骤 12: 完成刷新
            finishrefresh();
        } catch (beansexception ex) {
            // 异常处理...
        } finally {
            resetcommoncaches();
            contextrefresh.end();
        }
    }
}

3.2 bean 创建生命周期

// 单个 bean 的完整创建过程
1. 实例化 bean (构造函数调用)
2. 属性注入 (@autowired, @value, @resource)
3. aware 接口回调 (beannameaware, beanfactoryaware, applicationcontextaware)
4. beanpostprocessor.postprocessbeforeinitialization()
5. @postconstruct 方法执行
6. initializingbean.afterpropertiesset() 执行
7. 自定义初始化方法 (init-method)
8. beanpostprocessor.postprocessafterinitialization()
9. bean 就绪,加入单例池
10. 应用场景:
    - 单例 bean: 启动时创建
    - 原型 bean: 每次获取时创建
    - 延迟加载: 第一次使用时创建

4. spring boot 自动配置机制

4.1 条件化配置加载

// 自动配置原理
@springbootapplication
├── @springbootconfiguration
├── @enableautoconfiguration
│   └── @import(autoconfigurationimportselector.class)
└── @componentscan

// autoconfigurationimportselector 工作流程:
1. 加载 meta-inf/spring.factories 中所有 enableautoconfiguration 配置
2. 根据条件注解过滤:
   - @conditionalonclass
   - @conditionalonbean
   - @conditionalonproperty
   - @conditionalonwebapplication
   - @conditionalonmissingbean
3. 按 @autoconfigureorder、@order 排序
4. 去重并应用配置类

4.2 内嵌 web 服务器启动

// tomcat 启动详细过程
1. servletwebserverapplicationcontext.onrefresh()
2. createwebserver() 创建 webserver
3. tomcatservletwebserverfactory.getwebserver()
   - 创建 tomcat 实例
   - 配置 engine 和 host
   - 创建 connector(配置端口、协议等)
   - 创建 context 并配置
   - 加载 dispatcherservlet
   - 配置 session、errorpage 等
4. 启动 tomcat
   - 启动 connector 监听端口
   - 启动 engine 处理请求
5. 发布 servletwebserverinitializedevent

服务器部署启动的详细过程

1. 打包与部署准备

1.1 可执行 jar 结构

my-application.jar
├── meta-inf/
│   └── manifest.mf
├── boot-inf/
│   ├── classes/          # 应用类文件
│   │   ├── com/yourcompany/application.class
│   │   └── application.properties
│   └── lib/              # 依赖库
│       ├── spring-boot-2.7.x.jar
│       ├── spring-core-5.3.x.jar
│       └── ...
└── org/springframework/boot/loader/
    ├── jarlauncher.class
    └── launchedurlclassloader.class

1.2 启动脚本示例

#!/bin/bash
# 生产环境启动脚本

# jvm 参数配置
java_opts="-server -xms2g -xmx2g -xx:+useg1gc"
java_opts="$java_opts -xx:maxgcpausemillis=200"
java_opts="$java_opts -dspring.profiles.active=prod"
java_opts="$java_opts -dlogging.file=/var/log/myapp/application.log"

# 启动应用
java $java_opts -jar my-application.jar

2. 生产环境启动流程

2.1 启动类加载器机制

// spring boot launcher 工作机制
jarlauncher -> launchedurlclassloader
    ↓
加载 boot-inf/classes 和 boot-inf/lib/*.jar
    ↓
反射调用应用的 main 方法
    ↓
后续流程与 idea 启动相同

2.2 生产环境特定配置

# application-prod.yml
spring:
  datasource:
    url: jdbc:mysql://prod-db:3306/myapp
    username: ${db_username}
    password: ${db_password}
  redis:
    host: redis-cluster
    port: 6379
    
server:
  port: 8080
  compression:
    enabled: true
  servlet:
    session:
      timeout: 30m

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
  endpoint:
    health:
      show-details: always

本地启动与服务器启动的异同点对比

1. 环境配置差异

特性idea 本地启动服务器部署启动
类加载机制标准 classloaderlaunchedurlclassloader
配置文件加载文件系统直接读取jar 包内资源读取
热部署支持devtools 自动重启需要手动重启
调试支持完整调试功能远程调试需配置
资源监控idea 内置工具jmx/actuator 监控

2. 性能特征对比

2.1 启动时间分析

// 本地开发环境(idea)
启动阶段                 | 时间占比
------------------------------------
类路径扫描和加载        | 15-20%
bean 定义解析          | 20-25%
bean 实例化和依赖注入  | 30-35%
web 服务器启动         | 15-20%
其他初始化            | 10-15%

// 生产服务器环境
启动阶段                 | 时间占比
------------------------------------
jar 解压和类加载       | 25-30%
bean 定义解析          | 20-25%
bean 实例化和依赖注入  | 25-30%
web 服务器启动         | 15-20%
其他初始化            | 5-10%

2.2 内存使用对比

// 开发环境典型内存配置
-xms512m -xmx1024m -xx:maxmetaspacesize=256m

// 生产环境典型内存配置  
-xms2g -xmx2g -xx:maxmetaspacesize=512m
-xx:+useg1gc -xx:maxgcpausemillis=200

3. 配置管理差异

3.1 配置文件加载策略

# 开发环境配置优先级
1. @testpropertysource
2. 命令行参数 (idea run configuration)
3. spring_application_json
4. servletconfig 初始化参数
5. servletcontext 初始化参数  
6. jndi 属性
7. java 系统属性
8. 操作系统环境变量
9. random.* 属性
10. application-{profile}.properties/yml
11. application.properties/yml
12. @propertysource
13. 默认属性

# 生产环境配置优先级
1. 命令行参数 (启动脚本)
2. spring_application_json
3. java 系统属性  
4. 操作系统环境变量
5. random.* 属性
6. application-{profile}.properties/yml (打包在jar内)
7. application.properties/yml (打包在jar内)
8. 默认属性

3.2 日志配置差异

# 开发环境日志配置
logging:
  level:
    com.yourcompany: debug
    org.springframework: info
  pattern:
    console: "%clr(%d{hh:mm:ss.sss}){faint} %clr(%-5level) %clr(${pid}){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex"

# 生产环境日志配置  
logging:
  file:
    path: /var/log/myapp
    name: /var/log/myapp/application.log
  level:
    com.yourcompany: info
    org.springframework: warn
  pattern:
    file: "%d{yyyy-mm-dd hh:mm:ss.sss} [%thread] %-5level %logger{36} - %msg%n"
    console: "%d{yyyy-mm-dd hh:mm:ss.sss} [%thread] %-5level %logger{36} - %msg%n"

4. 监控和管理差异

4.1 开发环境监控

// idea 内置工具
- 内存使用情况实时监控
- cpu 使用率分析
- 线程状态查看
- 断点调试和变量查看
- 方法执行时间分析

// spring boot devtools
- 自动重启
- livereload
- 全局配置
- 远程调试支持

4.2 生产环境监控

# spring boot actuator 配置
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,env,beans
      base-path: /manage
  endpoint:
    health:
      show-details: always
      probes:
        enabled: true
    metrics:
      enabled: true
  metrics:
    export:
      prometheus:
        enabled: true

# 健康检查配置
spring:
  boot:
    admin:
      client:
        url: http://monitoring-server:8080

性能优化建议

1. 启动性能优化

1.1 类路径优化

// 减少不必要的依赖
@springbootapplication
// 排除不必要的自动配置
@enableautoconfiguration(exclude = {
    datasourceautoconfiguration.class,
    datasourcetransactionmanagerauto.class
})
public class application {
    // 延迟初始化配置
    public static void main(string[] args) {
        springapplication app = new springapplication(application.class);
        app.setlazyinitialization(true);  // 延迟初始化
        app.run(args);
    }
}

1.2 bean 初始化优化

@component
public class heavybean {
    
    @postconstruct
    public void init() {
        // 异步初始化耗时操作
        completablefuture.runasync(() -> {
            // 耗时初始化逻辑
            heavyinitialization();
        });
    }
    
    // 使用 @lazy 延迟加载
    @bean
    @lazy
    public expensiveservice expensiveservice() {
        return new expensiveservice();
    }
}

2. 内存使用优化

2.1 jvm 参数调优

# 生产环境推荐配置
java -server -xms2g -xmx2g \
     -xx:+useg1gc -xx:maxgcpausemillis=200 \
     -xx:initiatingheapoccupancypercent=45 \
     -xx:+explicitgcinvokesconcurrent \
     -xlog:gc*:file=/var/log/myapp/gc.log:time,uptime,level,tags:filecount=5,filesize=10m \
     -jar my-application.jar

常见问题与解决方案

1. 启动失败问题

1.1 类冲突问题

// 解决方案:排除冲突依赖
<dependency>
    <groupid>com.some.library</groupid>
    <artifactid>problematic-lib</artifactid>
    <exclusions>
        <exclusion>
            <groupid>commons-logging</groupid>
            <artifactid>commons-logging</artifactid>
        </exclusion>
    </exclusions>
</dependency>

// 或者使用 dependencymanagement 统一版本
<dependencymanagement>
    <dependencies>
        <dependency>
            <groupid>com.fasterxml.jackson.core</groupid>
            <artifactid>jackson-bom</artifactid>
            <version>2.13.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencymanagement>

1.2 配置加载问题

# 配置加载顺序问题解决方案
# 1. 使用明确的配置文件
spring.config.location=classpath:/,classpath:/config/,file:./,file:./config/

# 2. 环境变量覆盖
export spring_application_json='{"server":{"port":8080}}'

# 3. 配置属性验证
@component
@configurationproperties(prefix = "app.datasource")
@validated
public class datasourceproperties {
    @notempty
    private string url;
    
    // getters and setters
}

2. 性能问题诊断

2.1 启动时间分析

// 启用启动时间监控
@springbootapplication
public class application {
    
    public static void main(string[] args) {
        springapplication app = new springapplication(application.class);
        
        // 添加启动监听器记录时间
        app.addlisteners(new applicationlistener<applicationreadyevent>() {
            @override
            public void onapplicationevent(applicationreadyevent event) {
                // 记录启动时间
                log.info("application started in {} seconds", 
                    managementfactory.getruntimemxbean().getuptime() / 1000.0);
            }
        });
        
        app.run(args);
    }
}

// 或者使用 spring boot 的启动指标
management.endpoints.web.exposure.include=startup

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com