Spring MVC容器的启动和关闭时机与部署方式密切相关。
主要有两种部署方式:传统WAR包部署和Spring Boot嵌入式容器部署。

1. 传统WAR包部署(外部Servlet容器:Tomcat、Jetty等)
启动时机
web.xml
<!-- web.xml 配置 -->
<web-app>
    <!-- 1. 根容器(Service、Repository等)启动 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- 2. Spring MVC容器(Controller、HandlerMapping等)启动 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <!-- 启动顺序:应用启动时立即加载 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
</web-app>

#启动流程:

Servlet容器启动 → 应用部署
ContextLoaderListener.contextInitialized() → 创建根WebApplicationContext(父容器)
DispatcherServlet.init() → 创建WebApplicationContext(子容器,继承父容器)
所有单例Bean初始化完成 → 应用就绪

#关闭时机
// 关闭流程:
1. Servlet容器关闭(如关闭Tomcat)
2. ContextLoaderListener.contextDestroyed() → 关闭根容器
3. DispatcherServlet.destroy() → 关闭MVC容器
4. 所有Bean的@PreDestroy方法执行 → 资源清理
2. Spring Boot嵌入式容器部署

#启动时机
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        // 容器在此启动!
        SpringApplication.run(Application.class, args);
    }
}

#启动流程:
SpringApplication.run() 调用
创建统一的ApplicationContext(不再区分根容器和MVC容器)
嵌入式Servlet容器(Tomcat/Netty)启动
DispatcherServlet自动注册
所有Bean初始化完成
应用开始监听端口

#关闭时机
优雅关闭(推荐)
application.yaml
# application.yml
server:
  shutdown: graceful  # 优雅关闭
spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s  # 等待超时时间

#关闭方式:
Ctrl+C 发送SIGINT信号
发送SIGTERM信号:kill -15 <pid>
通过Actuator端点(如果配置了):

curl -X POST http://localhost:8080/actuator/shutdown

#关闭流程:

// Spring Boot 优雅关闭流程
1. 收到关闭信号
2. 停止接收新请求
3. 等待正在处理的请求完成(最多等待timeout时间)
4. 关闭ApplicationContext
5. 销毁所有Bean,执行@PreDestroy
6. 关闭嵌入式Servlet容器
7. JVM退出
3. 关键生命周期回调

@Component
public class LifecycleExample {
    
    // 启动时执行
    @PostConstruct
    public void init() {
        System.out.println("Bean初始化完成");
    }
    
    // 关闭时执行
    @PreDestroy  
    public void cleanup() {
        System.out.println("Bean销毁前清理资源");
    }
}

// 实现接口方式
@Component
public class LifecycleListener implements SmartLifecycle {
    private boolean isRunning = false;
    
    @Override
    public void start() {
        isRunning = true;
        System.out.println("容器启动时调用");
    }
    
    @Override
    public void stop() {
        isRunning = false;
        System.out.println("容器关闭时调用");
    }
    
    @Override
    public boolean isRunning() {
        return isRunning;
    }
}

总结
部署方式	|启动时机						|关闭时机				|特点
传统WAR		|Servlet容器启动时				|Servlet容器关闭时		|父子容器结构,生命周期由外部容器管理
Spring Boot	|SpringApplication.run()调用时	|收到关闭信号时			|统一容器,支持优雅关闭,更现代化

#核心要点:
Spring MVC容器的生命周期与Servlet容器紧密绑定
Spring Boot简化了生命周期管理,提供更友好的启停控制
生产环境推荐使用Spring Boot的优雅关闭机制

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐