启动过程及原理
1 spring boot 应用启动运行run方法
StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); //创建一个ApplicationContext容器 context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); //刷新IOC容器 refreshContext(context); afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); }
2 createApplicationContext():创建IOC容器,如果是web应用则创建AnnotationConfigEmbeddedWebApplacation的IOC容器,如果不是,则创建AnnotationConfigApplication的IOC容器
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context." + "annotation.AnnotationConfigApplicationContext";protected ConfigurableApplicationContext createApplicationContext() {</span><span style="color: #008000;">/*</span><span style="color: #008000;">* * The class name of application context that will be used by default for web * environments. </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> final String DEFAULT_WEB_CONTEXT_CLASS = <span style="color: #800000;">"</span><span style="color: #800000;">org.springframework.</span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;">boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext</span><span style="color: #800000;">"</span><span style="color: #000000;">;
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
//根据应用环境,创建不同的IOC容器
contextClass = Class.forName(this.webEnvironment
? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);
}
3 refreshContext(context) spring boot刷新IOC容器(创建容器对象,并初始化容器,创建容器每一个组件)
private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { // Not allowed in some environments. } } }
4 refresh(context);刷新刚才创建的IOC容器
protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); }
5 调用父类的refresh()的方法
public void refresh() throws BeansException, IllegalStateException { Object var1 = this.startupShutdownMonitor; synchronized(this.startupShutdownMonitor) { this.prepareRefresh(); ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); this.prepareBeanFactory(beanFactory);</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.postProcessBeanFactory(beanFactory); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.invokeBeanFactoryPostProcessors(beanFactory); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.registerBeanPostProcessors(beanFactory); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.initMessageSource(); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.initApplicationEventMulticaster(); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.onRefresh(); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.registerListeners(); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.finishBeanFactoryInitialization(beanFactory); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.finishRefresh(); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (BeansException var9) { </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.logger.isWarnEnabled()) { </span><span style="color: #0000ff;">this</span>.logger.warn(<span style="color: #800000;">"</span><span style="color: #800000;">Exception encountered during context initialization - cancelling refresh attempt: </span><span style="color: #800000;">"</span> +<span style="color: #000000;"> var9); } </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.destroyBeans(); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.cancelRefresh(var9); </span><span style="color: #0000ff;">throw</span><span style="color: #000000;"> var9; } </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.resetCommonCaches(); } } }</span></pre>
6 抽象父类AbstractApplicationContext类的子类EmbeddedWebApplicationContext的onRefresh方法
@Override protected void onRefresh() { super.onRefresh(); try { createEmbeddedServletContainer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start embedded container", ex); } }
7 在createEmbeddedServletContainer放啊发中会获取嵌入式Servlet容器工厂,由容器工厂创建Servlet
private void createEmbeddedServletContainer() { EmbeddedServletContainer localContainer = this.embeddedServletContainer; ServletContext localServletContext = getServletContext(); if (localContainer == null && localServletContext == null) {
//获取嵌入式Servlet容器工厂 EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
//根据容器工厂获取对应嵌入式Servlet容器 this.embeddedServletContainer = containerFactory .getEmbeddedServletContainer(getSelfInitializer()); } else if (localServletContext != null) { try { getSelfInitializer().onStartup(localServletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } initPropertySources(); }
8 从IOC容器中获取Servlet容器工厂
//EmbeddedWebApplicationContext#getEmbeddedServletContainerFactory protected EmbeddedServletContainerFactory getEmbeddedServletContainerFactory() { // Use bean names so that we don't consider the hierarchy String[] beanNames = getBeanFactory() .getBeanNamesForType(EmbeddedServletContainerFactory.class); if (beanNames.length == 0) { throw new ApplicationContextException( "Unable to start EmbeddedWebApplicationContext due to missing " + "EmbeddedServletContainerFactory bean."); } if (beanNames.length > 1) { throw new ApplicationContextException( "Unable to start EmbeddedWebApplicationContext due to multiple " + "EmbeddedServletContainerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames)); } return getBeanFactory().getBean(beanNames[0], EmbeddedServletContainerFactory.class); }
9 使用Servlet容器工厂获取嵌入式Servlet容器,具体使用哪一个容器工厂看配置环境依赖
this.embeddedServletContainer = containerFactory .getEmbeddedServletContainer(getSelfInitializer());
10 上述创建过程 首先启动IOC容器,接着启动嵌入式Servlet容器,接着将IOC容器中剩下没有创建的对象获取出来,比如自己创建的controller
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); }</span><span style="color: #008000;">//</span><span style="color: #008000;"> Register a default embedded value resolver if no bean post-processor </span><span style="color: #008000;">//</span><span style="color: #008000;"> (such as a PropertyPlaceholderConfigurer bean) registered any before: </span><span style="color: #008000;">//</span><span style="color: #008000;"> at this point, primarily for resolution in annotation attribute values.</span> <span style="color: #0000ff;">if</span> (!<span style="color: #000000;">beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> StringValueResolver() { @Override </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String resolveStringValue(String strVal) { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> getEnvironment().resolvePlaceholders(strVal); } }); } </span><span style="color: #008000;">//</span><span style="color: #008000;"> Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.</span> String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.<span style="color: #0000ff;">class</span>, <span style="color: #0000ff;">false</span>, <span style="color: #0000ff;">false</span><span style="color: #000000;">); </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } </span><span style="color: #008000;">//</span><span style="color: #008000;"> Stop using the temporary ClassLoader for type matching.</span> beanFactory.setTempClassLoader(<span style="color: #0000ff;">null</span><span style="color: #000000;">); </span><span style="color: #008000;">//</span><span style="color: #008000;"> Allow for caching all bean definition metadata, not expecting further changes.</span>
beanFactory.freezeConfiguration();
</span><span style="color: #008000;">//</span><span style="color: #008000;"> Instantiate all remaining (non-lazy-init) singletons.</span>
beanFactory.preInstantiateSingletons();
}
看看 preInstantiateSingletons方法
public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); }List</span><String> beanNames = <span style="color: #0000ff;">new</span> ArrayList(<span style="color: #0000ff;">this</span><span style="color: #000000;">.beanDefinitionNames); Iterator var2 </span>=<span style="color: #000000;"> beanNames.iterator(); </span><span style="color: #0000ff;">while</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">while</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">) { String beanName; RootBeanDefinition bd; </span><span style="color: #0000ff;">do</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">do</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">do</span><span style="color: #000000;"> { </span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">var2.hasNext()) { var2 </span>=<span style="color: #000000;"> beanNames.iterator(); </span><span style="color: #0000ff;">while</span><span style="color: #000000;">(var2.hasNext()) { beanName </span>=<span style="color: #000000;"> (String)var2.next(); Object singletonInstance </span>= <span style="color: #0000ff;">this</span><span style="color: #000000;">.getSingleton(beanName); </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton </span>=<span style="color: #000000;"> (SmartInitializingSingleton)singletonInstance; </span><span style="color: #0000ff;">if</span> (System.getSecurityManager() != <span style="color: #0000ff;">null</span><span style="color: #000000;">) { AccessController.doPrivileged(</span><span style="color: #0000ff;">new</span> PrivilegedAction<Object><span style="color: #000000;">() { </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object run() { smartSingleton.afterSingletonsInstantiated(); </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">; } }, </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.getAccessControlContext()); } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> { smartSingleton.afterSingletonsInstantiated(); } } } </span><span style="color: #0000ff;">return</span><span style="color: #000000;">; } beanName </span>=<span style="color: #000000;"> (String)var2.next(); bd </span>= <span style="color: #0000ff;">this</span><span style="color: #000000;">.getMergedLocalBeanDefinition(beanName); } </span><span style="color: #0000ff;">while</span><span style="color: #000000;">(bd.isAbstract()); } </span><span style="color: #0000ff;">while</span>(!<span style="color: #000000;">bd.isSingleton()); } </span><span style="color: #0000ff;">while</span><span style="color: #000000;">(bd.isLazyInit()); </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.isFactoryBean(beanName)) { final FactoryBean</span><?> factory = (FactoryBean)<span style="color: #0000ff;">this</span>.getBean(<span style="color: #800000;">"</span><span style="color: #800000;">&</span><span style="color: #800000;">"</span> +<span style="color: #000000;"> beanName); boolean isEagerInit; </span><span style="color: #0000ff;">if</span> (System.getSecurityManager() != <span style="color: #0000ff;">null</span> &&<span style="color: #000000;"> factory instanceof SmartFactoryBean) { isEagerInit </span>= ((Boolean)AccessController.doPrivileged(<span style="color: #0000ff;">new</span> PrivilegedAction<Boolean><span style="color: #000000;">() { </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Boolean run() { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ((SmartFactoryBean)factory).isEagerInit(); } }, </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.getAccessControlContext())).booleanValue(); } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> { isEagerInit </span>= factory instanceof SmartFactoryBean &&<span style="color: #000000;"> ((SmartFactoryBean)factory).isEagerInit(); } </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (isEagerInit) { </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.getBean(beanName); } } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {<br> //注册bean </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.getBean(beanName); } } } }</span></pre>
是使用getBean方法来通过反射将所有未创建的实例创建出来
使用嵌入式Servlet容器:
优点: 简单,便携
缺点: 默认不支持jsp,优化定制比较复杂
使用外置Servlet容器的步骤:
1 必须创建war项目,需要剑豪web项目的目录结构
2 嵌入式Tomcat依赖scope指定provided
3 编写SpringBootServletInitializer类子类,并重写configure方法
public class ServletInitializer extends SpringBootServletInitializer {@Override </span><span style="color: #0000ff;">protected</span><span style="color: #000000;"> SpringApplicationBuilder configure(SpringApplicationBuilder application) { </span><span style="color: #0000ff;">return</span> application.sources(SpringBoot04WebJspApplication.<span style="color: #0000ff;">class</span><span style="color: #000000;">); }
}
4 启动服务器
jar包和war包启动区别
jar包:执行SpringBootApplication的run方法,启动IOC容器,然后创建嵌入式Servlet容器
war包: 先是启动Servlet服务器,服务器启动Springboot应用(springBootServletInitizer),然后启动IOC容器
Servlet 3.0+规则
1 服务器启动(web应用启动),会创建当前web应用里面所有jar包里面的ServletContainerlnitializer实例
2 ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下
3 还可以使用@HandlesTypes注解,在应用启动的时候加载指定的类。
外部Tomcat流程以及原理
① 启动Tomcat
② 根据上述描述的Servlet3.0+规则,可以在Spring的web模块里面找到有个文件名为javax.servlet.ServletContainerInitializer的文件,而文件的内容为org.springframework.web.SpringServletContainerInitializer,用于加载SpringServletContainerInitializer类
③看看SpringServletContainerInitializer定义
@HandlesTypes(WebApplicationInitializer.class) public class SpringServletContainerInitializer implements ServletContainerInitializer {</span><span style="color: #008000;">/*</span><span style="color: #008000;">* * Delegate the {@code ServletContext} to any {@link WebApplicationInitializer} * implementations present on the application classpath. * <p>Because this class declares @{@code HandlesTypes(WebApplicationInitializer.class)}, * Servlet 3.0+ containers will automatically scan the classpath for implementations * of Spring's {@code WebApplicationInitializer} interface and provide the set of all * such types to the {@code webAppInitializerClasses} parameter of this method. * <p>If no {@code WebApplicationInitializer} implementations are found on the classpath, * this method is effectively a no-op. An INFO-level log message will be issued notifying * the user that the {@code ServletContainerInitializer} has indeed been invoked but that * no {@code WebApplicationInitializer} implementations were found. * <p>Assuming that one or more {@code WebApplicationInitializer} types are detected, * they will be instantiated (and <em>sorted</em> if the @{@link * org.springframework.core.annotation.Order @Order} annotation is present or * the {@link org.springframework.core.Ordered Ordered} interface has been * implemented). Then the {@link WebApplicationInitializer#onStartup(ServletContext)} * method will be invoked on each instance, delegating the {@code ServletContext} such * that each instance may register and configure servlets such as Spring's * {@code DispatcherServlet}, listeners such as Spring's {@code ContextLoaderListener}, * or any other Servlet API componentry such as filters. * @param webAppInitializerClasses all implementations of * {@link WebApplicationInitializer} found on the application classpath * @param servletContext the servlet context to be initialized * @see WebApplicationInitializer#onStartup(ServletContext) * @see AnnotationAwareOrderComparator </span><span style="color: #008000;">*/</span><span style="color: #000000;"> @Override </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> onStartup(Set<Class<?>><span style="color: #000000;"> webAppInitializerClasses, ServletContext servletContext) throws ServletException { List</span><WebApplicationInitializer> initializers = <span style="color: #0000ff;">new</span> LinkedList<WebApplicationInitializer><span style="color: #000000;">(); </span><span style="color: #0000ff;">if</span> (webAppInitializerClasses != <span style="color: #0000ff;">null</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">for</span> (Class<?><span style="color: #000000;"> waiClass : webAppInitializerClasses) { </span><span style="color: #008000;">//</span><span style="color: #008000;"> Be defensive: Some servlet containers provide us with invalid classes, </span><span style="color: #008000;">//</span><span style="color: #008000;"> no matter what @HandlesTypes says...</span> <span style="color: #0000ff;">if</span> (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&<span style="color: #000000;"> WebApplicationInitializer.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">.isAssignableFrom(waiClass)) { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br> //为所有的WebApplicationInitializer类型创建实例,并加入集合中 initializers.add((WebApplicationInitializer) waiClass.newInstance()); } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Throwable ex) { </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ServletException(<span style="color: #800000;">"</span><span style="color: #800000;">Failed to instantiate WebApplicationInitializer class</span><span style="color: #800000;">"</span><span style="color: #000000;">, ex); } } } } </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (initializers.isEmpty()) { servletContext.log(</span><span style="color: #800000;">"</span><span style="color: #800000;">No Spring WebApplicationInitializer types detected on classpath</span><span style="color: #800000;">"</span><span style="color: #000000;">); </span><span style="color: #0000ff;">return</span><span style="color: #000000;">; } servletContext.log(initializers.size() </span>+ <span style="color: #800000;">"</span><span style="color: #800000;"> Spring WebApplicationInitializers detected on classpath</span><span style="color: #800000;">"</span><span style="color: #000000;">); AnnotationAwareOrderComparator.sort(initializers);<br> //调用每一个WebApplicationInitializer实例的onstartup方法 </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (WebApplicationInitializer initializer : initializers) { initializer.onStartup(servletContext); } }
}
public abstract class SpringBootServletInitializer implements WebApplicationInitializer {@Override public void onStartup(ServletContext servletContext) throws ServletException { // Logger initialization is deferred in case a ordered // LogServletContextInitializer is being used this.logger = LogFactory.getLog(getClass()); //创建IOC容器 WebApplicationContext rootAppContext = createRootApplicationContext( servletContext); if (rootAppContext != null) { servletContext.addListener(new ContextLoaderListener(rootAppContext) { @Override public void contextInitialized(ServletContextEvent event) { // no-op because the application context is already initialized } }); } else { this.logger.debug("No ContextLoaderListener registered, as " + "createRootApplicationContext() did not " + "return an application context"); } }</span><span style="color: #008000;">//</span><span style="color: #008000;">other code... </span>
</span><span style="color: #0000ff;">protected</span><span style="color: #000000;"> WebApplicationContext createRootApplicationContext( ServletContext servletContext) { </span><span style="color: #008000;">//</span><span style="color: #008000;">创建Spring应用构建器,并进行相关属性设置 </span> SpringApplicationBuilder builder =<span style="color: #000000;"> createSpringApplicationBuilder(); StandardServletEnvironment environment </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> StandardServletEnvironment(); environment.initPropertySources(servletContext, </span><span style="color: #0000ff;">null</span><span style="color: #000000;">); builder.environment(environment); builder.main(getClass()); ApplicationContext parent </span>=<span style="color: #000000;"> getExistingRootWebApplicationContext(servletContext); </span><span style="color: #0000ff;">if</span> (parent != <span style="color: #0000ff;">null</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">this</span>.logger.info(<span style="color: #800000;">"</span><span style="color: #800000;">Root context already created (using as parent).</span><span style="color: #800000;">"</span><span style="color: #000000;">); servletContext.setAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, </span><span style="color: #0000ff;">null</span><span style="color: #000000;">); builder.initializers(</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> ParentContextApplicationContextInitializer(parent)); } builder.initializers( </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> ServletContextApplicationContextInitializer(servletContext)); builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">); </span><span style="color: #008000;">//</span><span style="color: #008000;">调用configure方法,创建war类型的web项目后,由于编写SpringBootServletInitializer的子类重写configure方法,所以此处调用的是我们定义的子类重写的configure方法 </span> builder =<span style="color: #000000;"> configure(builder); </span><span style="color: #008000;">//</span><span style="color: #008000;">通过构建器构建了一个Spring应用 </span> SpringApplication application =<span style="color: #000000;"> builder.build(); </span><span style="color: #0000ff;">if</span> (application.getSources().isEmpty() &&<span style="color: #000000;"> AnnotationUtils .findAnnotation(getClass(), Configuration.</span><span style="color: #0000ff;">class</span>) != <span style="color: #0000ff;">null</span><span style="color: #000000;">) { application.getSources().add(getClass()); } Assert.state(</span>!<span style="color: #000000;">application.getSources().isEmpty(), </span><span style="color: #800000;">"</span><span style="color: #800000;">No SpringApplication sources have been defined. Either override the </span><span style="color: #800000;">"</span> + <span style="color: #800000;">"</span><span style="color: #800000;">configure method or add an @Configuration annotation</span><span style="color: #800000;">"</span><span style="color: #000000;">); </span><span style="color: #008000;">//</span><span style="color: #008000;"> Ensure error pages are registered </span> <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.registerErrorPageFilter) { application.getSources().add(ErrorPageFilterConfiguration.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">); } </span><span style="color: #008000;">//</span><span style="color: #008000;">启动Spring应用 </span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> run(application); } </span><span style="color: #008000;">//</span><span style="color: #008000;">Spring应用启动,创建并返回IOC容器 </span> <span style="color: #0000ff;">protected</span><span style="color: #000000;"> WebApplicationContext run(SpringApplication application) { </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> (WebApplicationContext) application.run(); }
}
SpringBootServletInitializer实例执行onStartup方法的时候会通过createRootApplicationContext方法来执行run方法,接下来的过程就同以jar包形式启动的应用的run过程一样了,在内部会创建IOC容器并返回,只是以war包形式的应用在创建IOC容器过程中,不再创建Servlet容器了。