启动过程及原理

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. slice深拷贝数组

    var a = [1, 2, 3, 4] var b = a.slice(0) b[0] = 2 // a = [1, 2, 3, 4] // b = [2, 2, 3, 4]

  2. numpy_basic2

    # 六.numpy的常用函数 1. 读取文件 逻辑上可被解释为二维数组的文本文件: 数据项1<分隔符>数据项2<分隔符>...<分隔符>数据项n numpy.loa ...

  3. Docker+SVN

    原文:Docker+SVN mkdir /cnex/svndocker pull garethflowers/svn-server docker run -d --name svn-server  - ...

  4. POJ--1753--Flip Game【DFS】

    链接:http://poj.org/problem? id=1753 题意:一个4*4的方格,有白棋或者黑棋.每次操作是一个位置的颜色翻转,即白变黑.黑变白,而且与它相邻的四个位置的颜色也都跟着改变, ...

  5. ASP.Net MVC Filter验证用户登录

    一.Filter是什么 ASP.NetMVC模式自带的过滤器Filter,是一种声明式编程方式,支持四种过滤器类型,各自是:Authorization(授权),Action(行为),Result(结果 ...

  6. CODEVS——T 1993 草地排水 USACO

    http://codevs.cn/problem/1993/  时间限制: 2 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 De ...

  7. 洛谷 P1727 计算π

    P1727 计算π 题目背景 <爱与愁的故事第二弹·compute>第一章. 题目描述 中秋至,博饼声铿锵不断.爱与愁大神兴致勃勃地到学校博饼,结果抱回家的只有一秀二举.爱与愁大神十分生气 ...

  8. 防止登录页面出如今frame中

    在使用frame页面嵌套开发的时候,遇到重新启动了server的时候会出现登录页面在frame页面中出现, 所以须要在登录页面里面用js推断下当前的地址信息,然后跳转到登录的单独页面中. js代码例如 ...

  9. 阿里云部署Docker(3)----指令学习

    通过上两节的学习http://blog.csdn.net/minimicall/article/details/40119177 和http://blog.csdn.net/minimicall/ar ...

  10. SSH进阶(2)——用Struts拦截器实现登陆限制

    拦截器从字面意思来看就是限制.限制用户訪问某些网页.在Action提出请求之前用拦截器来做权限设置,让符合的用户跳入对应的界面中.近期做的一个商城项目中就用到了自己定义的拦截器,实现了一个简单的ses ...