spring boot中servlet启动原理
启动过程及原理
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><String> beanNames = <span style="color: #0000ff;">new</span> ArrayList(<span style="color: #0000ff;">this</span><span style="color: #000000;">.beanDefinitionNames);
Iterator var2 </span>=<span style="color: #000000;"> beanNames.iterator(); </span><span style="color: #0000ff;">while</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">) {
</span><span style="color: #0000ff;">while</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">) {
String beanName;
RootBeanDefinition bd;
</span><span style="color: #0000ff;">do</span><span style="color: #000000;"> {
</span><span style="color: #0000ff;">do</span><span style="color: #000000;"> {
</span><span style="color: #0000ff;">do</span><span style="color: #000000;"> {
</span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">var2.hasNext()) {
var2 </span>=<span style="color: #000000;"> beanNames.iterator(); </span><span style="color: #0000ff;">while</span><span style="color: #000000;">(var2.hasNext()) {
beanName </span>=<span style="color: #000000;"> (String)var2.next();
Object singletonInstance </span>= <span style="color: #0000ff;">this</span><span style="color: #000000;">.getSingleton(beanName);
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton </span>=<span style="color: #000000;"> (SmartInitializingSingleton)singletonInstance;
</span><span style="color: #0000ff;">if</span> (System.getSecurityManager() != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
AccessController.doPrivileged(</span><span style="color: #0000ff;">new</span> PrivilegedAction<Object><span style="color: #000000;">() {
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object run() {
smartSingleton.afterSingletonsInstantiated();
</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;
}
}, </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.getAccessControlContext());
} </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
smartSingleton.afterSingletonsInstantiated();
}
}
} </span><span style="color: #0000ff;">return</span><span style="color: #000000;">;
} beanName </span>=<span style="color: #000000;"> (String)var2.next();
bd </span>= <span style="color: #0000ff;">this</span><span style="color: #000000;">.getMergedLocalBeanDefinition(beanName);
} </span><span style="color: #0000ff;">while</span><span style="color: #000000;">(bd.isAbstract());
} </span><span style="color: #0000ff;">while</span>(!<span style="color: #000000;">bd.isSingleton());
} </span><span style="color: #0000ff;">while</span><span style="color: #000000;">(bd.isLazyInit()); </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.isFactoryBean(beanName)) {
final FactoryBean</span><?> factory = (FactoryBean)<span style="color: #0000ff;">this</span>.getBean(<span style="color: #800000;">"</span><span style="color: #800000;">&</span><span style="color: #800000;">"</span> +<span style="color: #000000;"> beanName);
boolean isEagerInit;
</span><span style="color: #0000ff;">if</span> (System.getSecurityManager() != <span style="color: #0000ff;">null</span> &&<span style="color: #000000;"> factory instanceof SmartFactoryBean) {
isEagerInit </span>= ((Boolean)AccessController.doPrivileged(<span style="color: #0000ff;">new</span> PrivilegedAction<Boolean><span style="color: #000000;">() {
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> Boolean run() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ((SmartFactoryBean)factory).isEagerInit();
}
}, </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.getAccessControlContext())).booleanValue();
} </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
isEagerInit </span>= factory instanceof SmartFactoryBean &&<span style="color: #000000;"> ((SmartFactoryBean)factory).isEagerInit();
} </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (isEagerInit) {
</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.getBean(beanName);
}
} </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {<br> //注册bean
</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.getBean(beanName);
}
}
}
}</span></pre>
是使用getBean方法来通过反射将所有未创建的实例创建出来
使用嵌入式Servlet容器:
优点: 简单,便携
缺点: 默认不支持jsp,优化定制比较复杂
使用外置Servlet容器的步骤:
1 必须创建war项目,需要剑豪web项目的目录结构
2 嵌入式Tomcat依赖scope指定provided
3 编写SpringBootServletInitializer类子类,并重写configure方法
public class ServletInitializer extends SpringBootServletInitializer {@Override
</span><span style="color: #0000ff;">protected</span><span style="color: #000000;"> SpringApplicationBuilder configure(SpringApplicationBuilder application) {
</span><span style="color: #0000ff;">return</span> application.sources(SpringBoot04WebJspApplication.<span style="color: #0000ff;">class</span><span style="color: #000000;">);
}
}
4 启动服务器
jar包和war包启动区别
jar包:执行SpringBootApplication的run方法,启动IOC容器,然后创建嵌入式Servlet容器
war包: 先是启动Servlet服务器,服务器启动Springboot应用(springBootServletInitizer),然后启动IOC容器
Servlet 3.0+规则
1 服务器启动(web应用启动),会创建当前web应用里面所有jar包里面的ServletContainerlnitializer实例
2 ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下
3 还可以使用@HandlesTypes注解,在应用启动的时候加载指定的类。
外部Tomcat流程以及原理
① 启动Tomcat
② 根据上述描述的Servlet3.0+规则,可以在Spring的web模块里面找到有个文件名为javax.servlet.ServletContainerInitializer的文件,而文件的内容为org.springframework.web.SpringServletContainerInitializer,用于加载SpringServletContainerInitializer类
③看看SpringServletContainerInitializer定义
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {</span><span style="color: #008000;">/*</span><span style="color: #008000;">*
* Delegate the {@code ServletContext} to any {@link WebApplicationInitializer}
* implementations present on the application classpath.
* <p>Because this class declares @{@code HandlesTypes(WebApplicationInitializer.class)},
* Servlet 3.0+ containers will automatically scan the classpath for implementations
* of Spring's {@code WebApplicationInitializer} interface and provide the set of all
* such types to the {@code webAppInitializerClasses} parameter of this method.
* <p>If no {@code WebApplicationInitializer} implementations are found on the classpath,
* this method is effectively a no-op. An INFO-level log message will be issued notifying
* the user that the {@code ServletContainerInitializer} has indeed been invoked but that
* no {@code WebApplicationInitializer} implementations were found.
* <p>Assuming that one or more {@code WebApplicationInitializer} types are detected,
* they will be instantiated (and <em>sorted</em> if the @{@link
* org.springframework.core.annotation.Order @Order} annotation is present or
* the {@link org.springframework.core.Ordered Ordered} interface has been
* implemented). Then the {@link WebApplicationInitializer#onStartup(ServletContext)}
* method will be invoked on each instance, delegating the {@code ServletContext} such
* that each instance may register and configure servlets such as Spring's
* {@code DispatcherServlet}, listeners such as Spring's {@code ContextLoaderListener},
* or any other Servlet API componentry such as filters.
* @param webAppInitializerClasses all implementations of
* {@link WebApplicationInitializer} found on the application classpath
* @param servletContext the servlet context to be initialized
* @see WebApplicationInitializer#onStartup(ServletContext)
* @see AnnotationAwareOrderComparator
</span><span style="color: #008000;">*/</span><span style="color: #000000;">
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> onStartup(Set<Class<?>><span style="color: #000000;"> webAppInitializerClasses, ServletContext servletContext)
throws ServletException { List</span><WebApplicationInitializer> initializers = <span style="color: #0000ff;">new</span> LinkedList<WebApplicationInitializer><span style="color: #000000;">(); </span><span style="color: #0000ff;">if</span> (webAppInitializerClasses != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {
</span><span style="color: #0000ff;">for</span> (Class<?><span style="color: #000000;"> waiClass : webAppInitializerClasses) {
</span><span style="color: #008000;">//</span><span style="color: #008000;"> Be defensive: Some servlet containers provide us with invalid classes,
</span><span style="color: #008000;">//</span><span style="color: #008000;"> no matter what @HandlesTypes says...</span>
<span style="color: #0000ff;">if</span> (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&<span style="color: #000000;">
WebApplicationInitializer.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">.isAssignableFrom(waiClass)) {
</span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br> //为所有的WebApplicationInitializer类型创建实例,并加入集合中
initializers.add((WebApplicationInitializer) waiClass.newInstance());
}
</span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Throwable ex) {
</span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ServletException(<span style="color: #800000;">"</span><span style="color: #800000;">Failed to instantiate WebApplicationInitializer class</span><span style="color: #800000;">"</span><span style="color: #000000;">, ex);
}
}
}
} </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (initializers.isEmpty()) {
servletContext.log(</span><span style="color: #800000;">"</span><span style="color: #800000;">No Spring WebApplicationInitializer types detected on classpath</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;
} servletContext.log(initializers.size() </span>+ <span style="color: #800000;">"</span><span style="color: #800000;"> Spring WebApplicationInitializers detected on classpath</span><span style="color: #800000;">"</span><span style="color: #000000;">);
AnnotationAwareOrderComparator.sort(initializers);<br> //调用每一个WebApplicationInitializer实例的onstartup方法
</span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
在上面一段长长的注释中可以看到,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() &&<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启动原理的更多相关文章
- spring boot(二):启动原理解析
我们开发任何一个Spring Boot项目,都会用到如下的启动类 @SpringBootApplication public class Application { public static voi ...
- 5、Spring Boot 2.x 启动原理解析
1.5 Spring Boot 启动原理解析 前言 前面几章我们见识了SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏 ...
- Spring Boot的自动配置原理及启动流程源码分析
概述 Spring Boot 应用目前应该是 Java 中用得最多的框架了吧.其中 Spring Boot 最具特点之一就是自动配置,基于Spring Boot 的自动配置,我们可以很快集成某个模块, ...
- Spring boot中使用servlet filter
Spring boot中使用servlet filter liuyuhang原创,未经允许请勿转载! 在web项目中经常需要一些场景,如参数过滤防止sql注入,防止页面攻击,空参数矫正等, 也可以做成 ...
- spring boot中使用servlet、listener和filter
spring boot中支持使用java Web三大组件(servlet.listener和filter),但是坑比较多,主要是spring boot内嵌tomcat和独立tomcat服务器有一些细节 ...
- Spring Boot 中的 Tomcat 是如何启动的?
作者:木木匠 https://my.oschina.net/luozhou/blog/3088908 我们知道 Spring Boot 给我们带来了一个全新的开发体验,让我们可以直接把 Web 程序打 ...
- 传统的Servlet在spring boot中怎么实现的?
传统的Servlet在spring boot中怎么实现的? 本文主要内容: 1:springboot一些介绍 2:传统的servlete项目在spring boot项目中怎么实现的?web.xml.u ...
- 从零开始的Spring Boot(2、在Spring Boot中整合Servlet、Filter、Listener的方式)
在Spring Boot中整合Servlet.Filter.Listener的方式 写在前面 从零开始的Spring Boot(1.搭建一个Spring Boot项目Hello World):http ...
- Spring Boot中Tomcat是怎么启动的
Spring Boot一个非常突出的优点就是不需要我们额外再部署Servlet容器,它内置了多种容器的支持.我们可以通过配置来指定我们需要的容器. 本文以我们平时最常使用的容器Tomcat为列来介绍以 ...
随机推荐
- cf1051F. The Shortest Statement(最短路/dfs树)
You are given a weighed undirected connected graph, consisting of nn vertices and mm edges. You shou ...
- SpringCloud核心教程 | 第三篇:服务注册与发现 Eureka篇
Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全 ...
- 【Codeforces Round #455 (Div. 2) C】 Python Indentation
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 一个for循环之后. 下一个写代码的地方一是从(x+1,y+1)开始的 然后如果写完了一个simple statement 下次就有 ...
- BFS模版程序
本文转自q=bfs&u=cnyali&t=blog">http://so.csdn.net/so/search/s.do?q=bfs&u=cnyali& ...
- Objective-C - 类的静态常量
创建头文件(.h), 导出常量: // Constants.h FOUNDATION_EXPORT NSString *const MyFirstConstant; FOUNDATION_EXPORT ...
- git 当出现 devirge 时,一个是commit的提交顺序不对
进入新分支1.git pull origin branchname 2.修改 3.git add . 4.git commit 5. git pull 6.git push 出现分歧要,就版本回退, ...
- 洛谷 P1599 结算日
洛谷 P1599 结算日 题目描述 “不放债不借债”,贝西多么希望自己可以遵循这个忠告.她已经和她的N(1 <= N <= 100,000)个朋友有了债务关系,或者借债了,或者放债了.她的 ...
- datagridview合并相同单元格
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { // 对第日 ...
- 编程——C语言的问题,堆栈
堆和栈的区别一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结 ...
- Keepalived + Mysql 双主
VIP 192.168.1.41 Master 192.168.1.42 Slave 192.168.1.43 .配置 yum -y install mysql-server chkconfig -- ...