SpringBoot系列之嵌入式servlet容器启动原理

嵌入式servlet容器启动原理

本文承接上一篇文章《SpringBoot系列之嵌入式servlet容器自动配置原理》,建议结合阅读,并结合源码深入理解。

本文将探讨以下问题:
什么时候创建嵌入式的Servlet容器工厂?什么时候获取嵌入式的Servlet容器并启动Tomcat;


1)、SpringBoot应用启动运行run方法
2)、refreshContext(context);SpringBoot刷新IOC容器【创建IOC容器对象,并初始化容器,创建容器中的每一
个组件】;如果是web应用创建:AnnotationConfigEmbeddedWebApplicationContext,否则创建:AnnotationConfigApplicationContext

public ConfigurableApplicationContext run(String... args) {
	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);
		// 创建IOC容器,如果是web应用创建AnnotationConfigEmbeddedWebApplicationContext
		// 否则创建AnnotationConfigApplicationContext
		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);
	}
}

3)、refresh(context);刷新刚才创建好的ioc容器;

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();
        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);
        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);
            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);
            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
            // Initialize message source for this context.
            initMessageSource();
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // SpringBoot web的ioc容器重写了onRefresh方法.
            onRefresh();
            // Check for listener beans and register them.
            registerListeners();
            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        } catch (BeansException ex) {
           // 源码省略 ...                
        } 
    }
}

4)、onRefresh(); web的ioc容器重写了onRefresh方法
5)、webIOC容器会创建嵌入式的Servlet容器;createEmbeddedServletContainer();
6)、获取嵌入式的Servlet容器工厂:
    EmbeddedServletContainerFactory containerFactory = getEmbeddedServletContainerFactory();
从ioc容器中获取EmbeddedServletContainerFactory 组件;TomcatEmbeddedServletContainerFactory创建
对象,后置处理器一看是这个对象,就获取所有的定制器来先定制Servlet容器的相关配置;(注:参考《SpringBoot系列之嵌入式servlet容器自动配置原理》)
7)、使用容器工厂获取嵌入式的Servlet容器:
    this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(getSelfInitializer());
8)、嵌入式的Servlet容器创建对象并启动Servlet容器;
    先启动嵌入式的Servlet容器,再将IOC容器中剩下没有创建出的对象获取出来;IOC容器启动创建嵌入式的Servlet容器

 

嵌入式的Servlet容器在企业级应用中可能存在一定的局限性,使用嵌入式Servlet容器:应用需打成可执行的jar
优点:简单、便携;
缺点:默认不支持JSP、
    优化定制比较复杂(使用定制器【ServerProperties、自定义EmbeddedServletContainerCustomizer】,自己编写嵌入式Servlet容器的创建工厂【EmbeddedServletContainerFactory】);

在大部分的企业应用中我们可能将项目打成war包,容器的一些参数配置到外置容器上,接下来的文章将探讨《外部Servlet容器启动SpringBoot应用》

你可能感兴趣的:(技术学习记录)