spring boot war包启动原理

spring boot war启动是利用Servlet 3.0新增的ServletContainerInitializer接口实现的。
 
主逻辑
  1. Spring在spring-web-version.jar/META-INF/services/javax.servlet.ServletContainerInitializer文件中,配置了spring对ServletContainerInitializer接口的实现类org.springframework.web.SpringServletContainerInitializer。
  2. Servlet Container启动阶段扫描jar包中META-INF/services/javax.servlet.ServletContainerInitializer文件, 获取ServletContainerInitializer实现类并实例化,解析ServletContainerInitializer上@HandlesTypes注解,查找出@HandlesTypes限定的类型集合,作为ServletContainerInitializer.onStartup 方法处理的第一个参数c。
  3. Servlet Container依次调用每个ServletContainerInitializer实例的onStartup。war包启动的场景中会调用SpringServletContainerInitializer.onStartup方法,该方法循环调用c集合中每个 WebApplicationInitializer子类(即SpringBootServletInitializer)的onStartup方法。
  4. SpringBootServletInitializer.onStartup方法调用SpringBootServletInitializer.createRootApplicationContext方法,createRootApplicationContext方法中构建SpringApplication并执行SpringApplication.run方法以启动整个spring项目。

源码

Spring的ServletContainerInitializer实现类

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
......
     @Override
     public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
              throws ServletException {
          List<WebApplicationInitializer> initializers = new LinkedList<>();
          if (webAppInitializerClasses != null) {
              for (Class<?> waiClass : webAppInitializerClasses) {
                   // Be defensive: Some servlet containers provide us with invalid classes,
                   // no matter what @HandlesTypes says...
                   if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
                             WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                        try {
                             initializers.add((WebApplicationInitializer)ReflectionUtils.accessibleConstructor(waiClass).newInstance());
                        } catch (Throwable ex) {
                             throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
                        }
                   }
              }
          }
          if (initializers.isEmpty()) {
              servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
              return;
          }
          servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
          AnnotationAwareOrderComparator.sort(initializers);
          for (WebApplicationInitializer initializer : initializers) {
              initializer.onStartup(servletContext);
          }
     }
}

WebApplicationInitializer.class接口的实现类

public abstract class SpringBootServletInitializer implements WebApplicationInitializer {
......
     @Override
     public void onStartup(ServletContext servletContext) throws ServletException {
          // Logger initialization is deferred in case an ordered
          // LogServletContextInitializer is being used
          this.logger = LogFactory.getLog(getClass());
          WebApplicationContext rootAppContext = createRootApplicationContext(servletContext);
          ......//略去部分代码
     }

     protected WebApplicationContext createRootApplicationContext(
              ServletContext servletContext) {
          SpringApplicationBuilder builder = createSpringApplicationBuilder();
          builder.main(getClass());
          ApplicationContext parent = getExistingRootWebApplicationContext(servletContext);
          ......//略去部分代码
          return run(application);
     }

    protected WebApplicationContext run(SpringApplication application) {
          return (WebApplicationContext) application.run();
     }

}

spring boot main application class

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
     
     public static void main(String[] args) {
          SpringApplication.run(Application.class, args);
     }
     
}

猜你喜欢

转载自www.cnblogs.com/stone-with-big-ears/p/10950581.html