启动过程及原理

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";
</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;">;

protected ConfigurableApplicationContext createApplicationContext() {

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 == ) {
throw new ApplicationContextException(
"Unable to start EmbeddedWebApplicationContext due to missing "
+ "EmbeddedServletContainerFactory bean.");
}
if (beanNames.length > ) {
throw new ApplicationContextException(
"Unable to start EmbeddedWebApplicationContext due to multiple "
+ "EmbeddedServletContainerFactory beans : "
+ StringUtils.arrayToCommaDelimitedString(beanNames));
}
return getBeanFactory().getBean(beanNames[],
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>&lt;String&gt; 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&lt;Object&gt;<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>&lt;?&gt; factory = (FactoryBean)<span style="color: #0000ff;">this</span>.getBean(<span style="color: #800000;">"</span><span style="color: #800000;">&amp;</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> &amp;&amp;<span style="color: #000000;"> factory instanceof SmartFactoryBean) {
isEagerInit </span>= ((Boolean)AccessController.doPrivileged(<span style="color: #0000ff;">new</span> PrivilegedAction&lt;Boolean&gt;<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 &amp;&amp;<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.
* &lt;p&gt;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.
* &lt;p&gt;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.
* &lt;p&gt;Assuming that one or more {@code WebApplicationInitializer} types are detected,
* they will be instantiated (and &lt;em&gt;sorted&lt;/em&gt; 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&lt;Class&lt;?&gt;&gt;<span style="color: #000000;"> webAppInitializerClasses, ServletContext servletContext)
throws ServletException { List</span>&lt;WebApplicationInitializer&gt; initializers = <span style="color: #0000ff;">new</span> LinkedList&lt;WebApplicationInitializer&gt;<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&lt;?&gt;<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() &amp;&amp; !Modifier.isAbstract(waiClass.getModifiers()) &amp;&amp;<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);
}
}

}

在上面一段长长的注释中可以看到,SpringServletContainerInitializer将@HandlesTypes(WebApplicationInitializer.class)标注的所有WebApplicationInitializer这个类型的类都传入到onStartup方法的Set参数中,并通过反射为这些WebApplicationInitializer类型的类创建实例;

  ④  方法最后,每一个WebApplicationInitilizer实现调用自己onstartup方法

  ⑤  而WebApplicationInitializer有个抽象实现类SpringBootServletInitializer(记住我们继承了该抽象类),则会调用每一个WebApplicationInitializer实例(包括SpringBootServletInitializer)的onStartup方法:

public abstract class SpringBootServletInitializer implements WebApplicationInitializer {  
</span><span style="color: #008000;">//</span><span style="color: #008000;">other code...  </span>

@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: #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() &amp;&amp;<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容器了。

原文地址:http://www.cnblogs.com/developerxiaofeng/p/9081689.html

spring boot中servlet启动原理的更多相关文章

  1. spring boot(二):启动原理解析

    我们开发任何一个Spring Boot项目,都会用到如下的启动类 @SpringBootApplication public class Application { public static voi ...

  2. 5、Spring Boot 2.x 启动原理解析

    1.5 Spring Boot 启动原理解析 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏 ...

  3. Spring Boot的自动配置原理及启动流程源码分析

    概述 Spring Boot 应用目前应该是 Java 中用得最多的框架了吧.其中 Spring Boot 最具特点之一就是自动配置,基于Spring Boot 的自动配置,我们可以很快集成某个模块, ...

  4. Spring boot中使用servlet filter

    Spring boot中使用servlet filter liuyuhang原创,未经允许请勿转载! 在web项目中经常需要一些场景,如参数过滤防止sql注入,防止页面攻击,空参数矫正等, 也可以做成 ...

  5. spring boot中使用servlet、listener和filter

    spring boot中支持使用java Web三大组件(servlet.listener和filter),但是坑比较多,主要是spring boot内嵌tomcat和独立tomcat服务器有一些细节 ...

  6. Spring Boot 中的 Tomcat 是如何启动的?

    作者:木木匠 https://my.oschina.net/luozhou/blog/3088908 我们知道 Spring Boot 给我们带来了一个全新的开发体验,让我们可以直接把 Web 程序打 ...

  7. 传统的Servlet在spring boot中怎么实现的?

    传统的Servlet在spring boot中怎么实现的? 本文主要内容: 1:springboot一些介绍 2:传统的servlete项目在spring boot项目中怎么实现的?web.xml.u ...

  8. 从零开始的Spring Boot(2、在Spring Boot中整合Servlet、Filter、Listener的方式)

    在Spring Boot中整合Servlet.Filter.Listener的方式 写在前面 从零开始的Spring Boot(1.搭建一个Spring Boot项目Hello World):http ...

  9. Spring Boot中Tomcat是怎么启动的

    Spring Boot一个非常突出的优点就是不需要我们额外再部署Servlet容器,它内置了多种容器的支持.我们可以通过配置来指定我们需要的容器. 本文以我们平时最常使用的容器Tomcat为列来介绍以 ...

随机推荐

  1. Docker 搭建java+tomcat

    1. 准备java和tomcat的软件包 jdk-7u79-linux-x64.tar.gz apache-tomcat-7.0.57.tar.gz 2. 编辑Dockerfile 文件 vim Do ...

  2. vue踩坑记- Cannot find module 'wrappy'

    找不到模块"包装" 当你维护别人的项目代码的时候,在自己这里电脑上运行,打开一个项目cnpm run dev的时候,报错如下 Cannot find module 'wrappy' ...

  3. listctrl调整表头高度

    CListCtrl派生类下CMyListCtrl.h class CMyListCtrl :public CListCtrl { public: // 设置表头高度 void SetHeadHeigh ...

  4. 【例题 7-14 UVA-1602】Lattice Animals

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 借鉴网上的题解的. 思路是. 用"标准化"的思想. 确定基准点(0,0) 然后假设(0,0)是第一个连通块. 然 ...

  5. powerdesigner逆向自动生成mysql说明文档、PDM

    做EDI的项目的时候,用到相关工具powerdesigner,正好我们的一个项目对数据设计阶段时相关文档没有很好的保存下来,查找了一下powderdesigner相关文档,采用逆向工程,从mysql数 ...

  6. 洛谷——P1042 乒乓球

    https://www.luogu.org/problem/show?pid=1042 题目背景 国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及.其中11分制改 ...

  7. [TS] Swap two element in the array (mutation)

    Shuffling is a common process used with randomizing the order for a deck of cards. The key property ...

  8. 7. Spring Boot 启动加载数据 CommandLineRunner

    转自:https://blog.csdn.net/catoop/article/details/50501710

  9. C# C++ 字符串传递

    C# C++ 字符串传递 标签: c#c++bytestring测试c 2012-06-14 17:425707人阅读评论(3)收藏举报 分类: C#(11)  作者同类文章X C++(112)  作 ...

  10. Mycat常见问题与解决方案---宜将剩勇追穷寇,不可沽名学霸王

    1 Mycat目前有哪些功能与特性? 答: • 支持 SQL 92标准 • 支持Mysql集群,可以作为Proxy使用 • 支持JDBC连接多数据库 • 支持NoSQL数据库 • 支持galera f ...