SpringBoot——外置Servlet容器启动SpringBoot应用的原理

本文详细解析了SpringBoot如何在外置Tomcat容器中启动应用的流程,涉及ServletContainerInitializer接口、SpringServletContainerInitializer类以及WebApplicationInitializer的作用。在Servlet3.1规范下,Tomcat启动时会实例化并调用ServletContainerInitializer的onStartup方法,SpringBoot应用的启动就在这个过程中完成。
摘要由CSDN通过智能技术生成

参考

1 前言

1.1 内嵌servlet 容器的情况下

根据SpringBoot的启动原理,可以知道,是通过以下代码可以直接,启动SpringBoot应用(就是SpringApplication.run(...)方法):

@SpringBootApplication
public class SpringBootApplicationStarter {
   

    public static void main(String[] args) {
   
        SpringApplication.run(SpringBootApplicationStarter.class, args);
    }

}

1.2 在外置servlet容器的情况下

同上,同样是调用了SpringApplication.run(...)方法,不过需要先启动 服务器,再间接创建->初始化->启动SpringBoot应用,以下就是这种情况下的SpringBoot启动流程:

这种启动流程原理,是依赖Servlet3.1规范的(大致如下):

  • 根据Servlet3.1规范,服务器启动(web应用启动)会创建当前web应用里面每一个jar包里面ServletContainerInitializer的实例。

  • ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下,有一个名为javax.servlet.ServletContainerInitializer的文件,内容就是ServletContainerInitializer的实现类的全类名

  • 在任何 Servlet Listener 的事件被触发之前,当应用正在启动时,ServletContainerInitializeronStartup 方法将被调用。

  • ServletContainerInitializer 实现上的@handlesTypes注解用于寻找感兴趣的类,要么是@HandlesTypes注解指定的类,要么是指定类的子类。

1.2.1 启动流程(以Tomcat为例)

  • Tomcat启动

  • 根据Servlet3.1规范,找到 ServletContainerInitializer 的实现,进行实例化

  • 创建 ServletContainerInitializer 实例

  • 调用 ServletContainerInitializer 实例 (SpringServletContainerInitializer)的 onStartup 方法

  • SpringBoot 应用,就是在 onStartup 方法中启动的

1.2.2 ServletContainerInitializer 接口

ServletContainerInitializer 就是一个接口,只有一个待实现的方法onStartup

// javax/servlet/ServletContainerInitializer.class
public interface ServletContainerInitializer {
   
    void onStartup(Set<Class<?>> var1, ServletContext var2) throws ServletException;
}

2 外置Tomcat启动SpringBoot的流程原理

2.1 Tomcat 启动

Tomcat启动原理

重点看下 StandardContext 类的 startInternal 方法

protected synchronized void startInternal() throws LifecycleException {
   

// 略

    // 调用 所有的 ServletContainerInitializer 的 onStartup 方法
    for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :
        initializers.entrySet()) {
   
        try {
   
            entry.getKey().onStartup(entry.getValue(),
                    getServletContext());
        } catch (ServletException e) {
   
            log.error(sm.getString("standardContext.sciFail"), e);
            ok = false;
            break;
        }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值