启动过程及原理

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. JSON.parse和eval()的区别

    eval方法不检查给的字符串是否符合json的格式,parse会检查json语法格式. 比如一个json字符串data: { "a": 1, "b": &quo ...

  2. Codeforces 718C. Sasha and Array(线段树)

    传送门 解题思路: 这道题给了我们一个崭新的角度来看线段树. 我们常常使用的线段树是维护区间的函数的. 这里呢,提示我们线段树其实还可以维护递推. 美好的矩阵递推性质支持了这一功能. 或者说,对于递推 ...

  3. WPF 入门《数据绑定》

    简单而言, 数据绑定是一种关系, 这种关系告诉WPF 从一个源目标对象中提取一些信息, 并且使用该信息设置为目标对象的属性.目标属性总是依赖项属性, 并且通常位于WPF元素中. 然而, 源对象可以是任 ...

  4. 如何使用maven 打包源代码呢?

    如何使用maven 打包源代码呢? http://hw1287789687.iteye.com/blog/1943157

  5. Java Drp项目实战——Servlet

    由来 在解说Servlet之前须要先介绍一个词语CGI即Common GatewayInterface是通用网关接口的意思.它提供一个计算机程序同HTTP协议或者WWW服务的接口,也就是人机交互接口的 ...

  6. 关于C++中的内存泄露

    1.c++内存泄漏的定义: 内存泄漏(memory leak)是指由于疏忽或错误造成了程序未能释放掉不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失 ...

  7. CSS外边距合并(塌陷/margin越界)

    原文 简书原文:https://www.jianshu.com/p/5f18f12cd162 大纲 1.什么是外边距合并?(折叠外边距) 2.外边距带来的影响 3.折叠的结果 4.产生折叠的原因 5. ...

  8. Java Web学习总结(15)——JSP指令

    一.JSP指令简介 JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分. 在JSP 2.0规范中共定义了三个指令: pa ...

  9. 魅族MX5和努比亚布拉格手机參数对照

    想买个Android手机锁定魅族MX5和努比亚布拉格.两个官网翻来翻去的非常难取舍,自己列了一个表对比了一下參数,本人喜欢薄一点的手机.有feel.參数对比表例如以下: 手机 魅族MX5 努比亚布拉格 ...

  10. CC2530定时器使用

     定时器学习   文件夹 说明 依据数据手冊可知CC2530总共同拥有4个定时器,可是定时器2被系统占用,可用的仅仅有三个,分别为定时器1/3/4 Timer在协议栈的代码位置为hal_timer ...