启动过程及原理

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. cf1051F. The Shortest Statement(最短路/dfs树)

    You are given a weighed undirected connected graph, consisting of nn vertices and mm edges. You shou ...

  2. SpringCloud核心教程 | 第三篇:服务注册与发现 Eureka篇

    Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全 ...

  3. 【Codeforces Round #455 (Div. 2) C】 Python Indentation

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 一个for循环之后. 下一个写代码的地方一是从(x+1,y+1)开始的 然后如果写完了一个simple statement 下次就有 ...

  4. BFS模版程序

    本文转自q=bfs&u=cnyali&t=blog">http://so.csdn.net/so/search/s.do?q=bfs&u=cnyali& ...

  5. Objective-C - 类的静态常量

    创建头文件(.h), 导出常量: // Constants.h FOUNDATION_EXPORT NSString *const MyFirstConstant; FOUNDATION_EXPORT ...

  6. git 当出现 devirge 时,一个是commit的提交顺序不对

    进入新分支1.git pull origin branchname 2.修改 3.git add . 4.git commit  5. git pull 6.git push 出现分歧要,就版本回退, ...

  7. 洛谷 P1599 结算日

    洛谷 P1599 结算日 题目描述 “不放债不借债”,贝西多么希望自己可以遵循这个忠告.她已经和她的N(1 <= N <= 100,000)个朋友有了债务关系,或者借债了,或者放债了.她的 ...

  8. datagridview合并相同单元格

    private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { // 对第日 ...

  9. 编程——C语言的问题,堆栈

    堆和栈的区别一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结 ...

  10. Keepalived + Mysql 双主

    VIP 192.168.1.41 Master 192.168.1.42 Slave 192.168.1.43 .配置 yum -y install mysql-server chkconfig -- ...