Spring Boot内嵌servlet容器启动原理源码分析

通过@AutoConfiguration注解加载ServletWebServerFactoryAutoConfiguration配置类,该类通过@Import注解导入符合条件的内嵌servlet容器的配置(EmbeddedTomcat、EmbeddedJetty、EmbeddedUndertow),注册对应的servletwebserver的bean信息,spring boot在执行run方法过程中,会执行onRefresh方法,在该方法中会进行webServer容器创建。

@Override
protected void onRefresh() {
   super.onRefresh();
   try {
       //执行创建webServer方法
      createWebServer();
   }
   catch (Throwable ex) {
      throw new ApplicationContextException("Unable to start web server", ex);
   }
}

createWebServer方法

private void createWebServer() {
   WebServer webServer = this.webServer;
   ServletContext servletContext = getServletContext();
   if (webServer == null && servletContext == null) {
       //获取IOC容器中的servletWebServerFactory(如果存在多个容器的jar时会抛异常)
      ServletWebServerFactory factory = getWebServerFactory();
      //创建servletWebServer
      this.webServer = factory.getWebServer(getSelfInitializer());
      //注册webServerLifecycle,在容器启动完成后(执行finishRefresh)调用
      getBeanFactory().registerSingleton("webServerGracefulShutdown",
            new WebServerGracefulShutdownLifecycle(this.webServer));
      //注册WebServerStartStopLifecycle,在IOC容器启动完成后,执行WebServer的start方法
      getBeanFactory().registerSingleton("webServerStartStop",
            new WebServerStartStopLifecycle(this, this.webServer));
   }
   else if (servletContext != null) {
      try {
         getSelfInitializer().onStartup(servletContext);
      }
      catch (ServletException ex) {
         throw new ApplicationContextException("Cannot initialize servlet context", ex);
      }
   }
   initPropertySources();
}

TomcatServletWebServerFactory的getWebServer方法

@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
   if (this.disableMBeanRegistry) {
      Registry.disableRegistry();
   }
   //创建tomcat
   Tomcat tomcat = new Tomcat();
   //设置tomcat参数
   File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
   tomcat.setBaseDir(baseDir.getAbsolutePath());
   for (LifecycleListener listener : this.serverLifecycleListeners) {
      tomcat.getServer().addLifecycleListener(listener);
   }
   //创建connector组件
   Connector connector = new Connector(this.protocol);
   connector.setThrowOnFailure(true);
   tomcat.getService().addConnector(connector);
   customizeConnector(connector);
   tomcat.setConnector(connector);
   tomcat.getHost().setAutoDeploy(false);
   configureEngine(tomcat.getEngine());
   for (Connector additionalConnector : this.additionalTomcatConnectors) {
      tomcat.getService().addConnector(additionalConnector);
   }
   prepareContext(tomcat.getHost(), initializers);
   //启动tomcat
   return getTomcatWebServer(tomcat);
}

Spring IOC容器启动完成后,在执行finishRefresh时,会调用DefaultLifecycleProcessor的onRefresh方法,最终调用容器中所有的SmartLifecycle对象的start方法。因在创建servletWebServer时,向容器中注册了WebServerStartStopLifecycle对象,因此在执行startBeans方法时,将会调用WebServerStartStopLifecycle的start方法启动servlet容器中的需要启动的servlet。

private void startBeans(boolean autoStartupOnly) {
    //获取IOC容器中所有的Lifecycle
   Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
   Map<Integer, LifecycleGroup> phases = new HashMap<>();
   lifecycleBeans.forEach((beanName, bean) -> {
      if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
         int phase = getPhase(bean);
         LifecycleGroup group = phases.get(phase);
         if (group == null) {
             //封装为group对象,避免多个Lifecycle的Phase相同被覆盖问题
            group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
            phases.put(phase, group);
         }
         group.add(beanName, bean);
      }
   });
   if (!phases.isEmpty()) {
       //对Phase进行升序排序
      List<Integer> keys = new ArrayList<>(phases.keySet());
      Collections.sort(keys);
      for (Integer key : keys) {
          //分组调用SmartLifecycle start方法
         phases.get(key).start();
      }
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值