25 Servlet容器启动原理

版权声明:看什么?6,你和我,走一波! https://blog.csdn.net/qq_31323797/article/details/84857530

1 SpringBoot项目启动

1.1 SpringBoot应用启动运行run方法

  • Springboot21Application
@SpringBootApplication
public class Springboot21Application {

    public static void main(String[] args) {
        SpringApplication.run(Springboot21Application.class, args);
    }
}
  • SpringApplication
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
	return (new SpringApplication(primarySources)).run(args);
}

public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
	this.configureHeadlessProperty();
	SpringApplicationRunListeners listeners = this.getRunListeners(args);
	listeners.starting();

	Collection exceptionReporters;
	try {
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
		this.configureIgnoreBeanInfo(environment);
		Banner printedBanner = this.printBanner(environment);
		
		// 创建IOC容器
		context = this.createApplicationContext();
		
		exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
		this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
		
		
		/*
			SpringBoot刷新IOC容器
				创建IOC容器对象,并初始化容器
				
				初始化容器: 创建容器中的每一个组件
		*/
		this.refreshContext(context);
		
		this.afterRefresh(context, applicationArguments);
		stopWatch.stop();
		if (this.logStartupInfo) {
			(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
		}

		listeners.started(context);
		this.callRunners(context, applicationArguments);
	} catch (Throwable var10) {
		this.handleRunFailure(context, var10, exceptionReporters, listeners);
		throw new IllegalStateException(var10);
	}
	
	......
}

protected ConfigurableApplicationContext createApplicationContext() {
	Class<?> contextClass = this.applicationContextClass;
	if (contextClass == null) {
		try {
			// 根据应用类型不同,创建不同容器
			switch(this.webApplicationType) {
			case SERVLET:
				contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");
				break;
			case REACTIVE:
				contextClass = Class.forName("org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext");
				break;
			default:
				contextClass = Class.forName("org.springframework.context.annotation.AnnotationConfigApplicationContext");
			}
		} catch (ClassNotFoundException var3) {
			throw new IllegalStateException("Unable create a default ApplicationContext, please specify an ApplicationContextClass", var3);
		}
	}

	return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
}
  • this.refreshContext(context) --> AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {
	synchronized(this.startupShutdownMonitor) {
		this.prepareRefresh();
		ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
		this.prepareBeanFactory(beanFactory);

		try {
			this.postProcessBeanFactory(beanFactory);
			this.invokeBeanFactoryPostProcessors(beanFactory);
			this.registerBeanPostProcessors(beanFactory);
			this.initMessageSource();
			this.initApplicationEventMulticaster();
			
			// web的ioc容器重写了onRefresh方法
			this.onRefresh();
			
			this.registerListeners();
			
			// 初始化IOC容器中剩余的单实例组件,eg:@Controller ,@Service
			this.finishBeanFactoryInitialization(beanFactory);
			this.finishRefresh();
		} catch (BeansException var9) {
			if (this.logger.isWarnEnabled()) {
				this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
			}

			this.destroyBeans();
			this.cancelRefresh(var9);
			throw var9;
		} finally {
			this.resetCommonCaches();
		}
	}
}
  • 重写onRefresh方法的容器
    重写onRefresh方法的容器

1.2 web的IOC容器会创建嵌入式的Servlet容器;createWebServer();

protected void onRefresh() {
	super.onRefresh();

	try {
		this.createWebServer();
	} catch (Throwable var2) {
		throw new ApplicationContextException("Unable to start web server", var2);
	}
}

1.3 获取嵌入式的Servlet容器工厂

private void createWebServer() {
	WebServer webServer = this.webServer;
	ServletContext servletContext = this.getServletContext();
	if (webServer == null && servletContext == null) {
	
		// 获取嵌入式的Servlet容器工厂
		ServletWebServerFactory factory = this.getWebServerFactory();
		this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()});
	} else if (servletContext != null) {
		try {
			this.getSelfInitializer().onStartup(servletContext);
		} catch (ServletException var4) {
			throw new ApplicationContextException("Cannot initialize servlet context", var4);
		}
	}

	this.initPropertySources();
}
  • getWebServerFactory()
protected ServletWebServerFactory getWebServerFactory() {
	String[] beanNames = this.getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
	if (beanNames.length == 0) {
		throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.");
	} else if (beanNames.length > 1) {
		throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
	} else {
		return (ServletWebServerFactory)this.getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
	}
}

在这里插入图片描述

​从ioc容器中获取TomcatServletWebServerFactory 并创建对象,后置处理器识别对象,然后获取所有的定制器来先定制Servlet容器的相关配置,详见24 Servlet容器配置原理

1.4 使用容器工厂获取嵌入式的Servlet容器

1.5 嵌入式的Servlet容器创建对象并启动Servlet容器;

1.6 先启动嵌入式的Servlet容器,再将ioc容器中剩下没有创建出的对象获取出来

1.7 IOC容器启动创建嵌入式的Servlet容器

猜你喜欢

转载自blog.csdn.net/qq_31323797/article/details/84857530
25