当前位置: 代码网 > it编程>编程语言>Java > SpringBoot通过main方法启动web项目实践

SpringBoot通过main方法启动web项目实践

2025年08月18日 Java 我要评论
spring boot 通过 main 方法启动 web 项目的过程涉及多个核心组件和自动化机制,下面从源码角度详细拆解:1. 启动入口:springapplication.run()@springb

spring boot 通过 main 方法启动 web 项目的过程涉及多个核心组件和自动化机制,下面从源码角度详细拆解:

1. 启动入口:springapplication.run()

@springbootapplication
public class demoapplication {
    public static void main(string[] args) {
        springapplication.run(demoapplication.class, args);
    }
}

springapplication.run() 是启动的核心入口,它主要完成以下工作:

2. springapplication初始化

// springapplication 构造函数核心逻辑
public springapplication(resourceloader resourceloader, class<?>... primarysources) {
    // 1. 设置资源加载器
    this.resourceloader = resourceloader;
    // 2. 校验并保存主配置类(即 @springbootapplication 标注的类)
    this.primarysources = new linkedhashset<>(arrays.aslist(primarysources));
    // 3. 推断应用类型(reactive、servlet、none)
    this.webapplicationtype = webapplicationtype.deducefromclasspath();
    // 4. 加载并实例化 applicationcontextinitializer
    setinitializers((collection) getspringfactoriesinstances(applicationcontextinitializer.class));
    // 5. 加载并实例化 applicationlistener
    setlisteners((collection) getspringfactoriesinstances(applicationlistener.class));
    // 6. 推断 main 方法所在类
    this.mainapplicationclass = deducemainapplicationclass();
}

关键步骤:

  • 应用类型推断:通过检查类路径中是否存在 org.springframework.web.reactive.dispatcherhandler(reactive)或 javax.servlet.servlet(servlet)来确定应用类型。
  • 初始化器(initializer):从 meta-inf/spring.factories 加载 applicationcontextinitializer,用于在 applicationcontext 刷新前自定义配置。
  • 监听器(listener):加载 applicationlistener,监听启动过程中的事件(如 applicationstartingevent)。

3. run()方法核心流程

public configurableapplicationcontext run(string... args) {
    // 1. 计时和发布启动事件
    stopwatch stopwatch = new stopwatch();
    stopwatch.start();
    configurableapplicationcontext context = null;
    collection<springbootexceptionreporter> exceptionreporters = new arraylist<>();
    configureheadlessproperty();
    
    // 2. 获取并启动监听器
    springapplicationrunlisteners listeners = getrunlisteners(args);
    listeners.starting();
    
    try {
        // 3. 构建应用参数和环境配置
        applicationarguments applicationarguments = new defaultapplicationarguments(args);
        configurableenvironment environment = prepareenvironment(listeners, applicationarguments);
        
        // 4. 创建并配置 applicationcontext
        context = createapplicationcontext();
        exceptionreporters = getspringfactoriesinstances(springbootexceptionreporter.class,
                new class[] { configurableapplicationcontext.class }, context);
        
        // 5. 准备上下文(加载 bean 定义)
        preparecontext(context, environment, listeners, applicationarguments, printedbanner);
        // 6. 刷新上下文(核心启动逻辑)
        refreshcontext(context);
        // 7. 刷新后的回调处理
        afterrefresh(context, applicationarguments);
        // 8. 发布应用就绪事件
        listeners.started(context);
        // 9. 执行 runner(如 commandlinerunner)
        callrunners(context, applicationarguments);
    }
    catch (throwable ex) {
        handlerunfailure(context, ex, exceptionreporters, listeners);
        throw new illegalstateexception(ex);
    }
    
    stopwatch.stop();
    if (this.logstartupinfo) {
        new startupinfologger(this.mainapplicationclass).logstarted(getapplicationlog(), stopwatch);
    }
    // 10. 发布应用运行中事件
    listeners.running(context);
    return context;
}

4. 嵌入式 web 服务器启动关键点

4.1refreshcontext()方法触发服务器启动

private void refreshcontext(configurableapplicationcontext context) {
    refresh(context);
    if (this.registershutdownhook) {
        try {
            context.registershutdownhook();
        }
        catch (accesscontrolexception ex) {
            // not allowed in some environments.
        }
    }
}

protected void refresh(configurableapplicationcontext context) {
    // 调用 abstractapplicationcontext 的 refresh() 方法
    context.refresh();
}

4.2servletwebserverapplicationcontext的核心作用

对于 web 应用,applicationcontext 实际类型为 annotationconfigservletwebserverapplicationcontext,它继承自 servletwebserverapplicationcontext,后者在 refresh() 过程中会:

// servletwebserverapplicationcontext 核心方法
@override
protected void onrefresh() {
    super.onrefresh();
    try {
        // 创建并启动嵌入式 web 服务器
        createwebserver();
    }
    catch (throwable ex) {
        throw new applicationcontextexception("unable to start web server", ex);
    }
}

private void createwebserver() {
    webserver webserver = this.webserver;
    servletcontext servletcontext = getservletcontext();
    
    if (webserver == null && servletcontext == null) {
        // 1. 获取 servletwebserverfactory(如 tomcatservletwebserverfactory)
        servletwebserverfactory factory = getwebserverfactory();
        // 2. 创建并配置 web 服务器
        this.webserver = factory.getwebserver(getselfinitializer());
    }
    else if (servletcontext != null) {
        try {
            getselfinitializer().onstartup(servletcontext);
        }
        catch (servletexception ex) {
            throw new applicationcontextexception("cannot initialize servlet context", ex);
        }
    }
    initpropertysources();
}

4.3servletwebserverfactory实例化服务器

以 tomcat 为例,tomcatservletwebserverfactorygetwebserver() 方法会:

@override
public webserver getwebserver(servletcontextinitializer... initializers) {
    // 1. 创建 tomcat 实例
    tomcat tomcat = new tomcat();
    // 2. 配置服务器基本参数(端口、上下文路径等)
    file basedir = (this.basedirectory != null) ? this.basedirectory : createtempdir("tomcat");
    tomcat.setbasedir(basedir.getabsolutepath());
    connector connector = new connector(this.protocol);
    tomcat.getservice().addconnector(connector);
    customizeconnector(connector);
    tomcat.setconnector(connector);
    tomcat.gethost().setautodeploy(false);
    // 3. 配置 servletcontextinitializer(如 dispatcherservlet)
    preparecontext(tomcat.gethost(), initializers);
    // 4. 启动服务器
    return gettomcatwebserver(tomcat);
}

5. spring mvc 组件自动配置

通过 webmvcautoconfiguration 自动配置核心组件:

  • dispatcherservlet:作为前端控制器,处理所有 http 请求。
  • handlermapping:映射 url 到具体的 controller 方法。
  • viewresolver:解析视图名称到实际视图。

关键代码(webmvcautoconfiguration):

@bean
@primary
@conditionalonmissingbean(dispatcherservlet.class)
public dispatcherservlet dispatcherservlet(webmvcproperties properties) {
    dispatcherservlet dispatcherservlet = new dispatcherservlet();
    dispatcherservlet.setdispatchoptionsrequest(properties.isdispatchoptionsrequest());
    dispatcherservlet.setdispatchtracerequest(properties.isdispatchtracerequest());
    dispatcherservlet.setthrowexceptionifnohandlerfound(properties.isthrowexceptionifnohandlerfound());
    dispatcherservlet.setpublishevents(properties.ispublishrequesthandledevents());
    dispatcherservlet.setenableloggingrequestdetails(properties.islogrequestdetails());
    return dispatcherservlet;
}

6. 最终启动结果

  • 嵌入式服务器(如 tomcat)启动并监听指定端口(默认 8080)。
  • dispatcherservlet 注册到 servlet 容器,作为所有请求的入口。
  • spring 上下文初始化完成,所有 bean 已加载并可用。
  • applicationreadyevent 发布,标志应用可处理外部请求。

总结:启动流程关键点

  1. springapplication 初始化:推断应用类型、加载初始化器和监听器。
  2. 环境配置:加载 application.properties 等配置源。
  3. applicationcontext 创建:根据 web 类型选择相应的上下文实现。
  4. 自动配置:基于依赖和条件注解,自动配置 web 组件(如 dispatcherservlet)。
  5. 嵌入式服务器启动:通过 servletwebserverfactory 创建并启动 tomcat/jetty。
  6. spring mvc 初始化:配置请求映射、视图解析等核心组件。

通过这种机制,spring boot 实现了“零配置”启动 web 项目的能力,开发者只需关注业务逻辑,无需手动处理服务器配置和组件装配。

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

(0)

相关文章:

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

发表评论

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