SpringBoot2.3.1嵌入式Servlet启动配置原理
从SpringBoot启动类开始看起
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
进入run方法
/** * Static helper that can be used to run a {@link SpringApplication} from the * specified sources using default settings and user supplied arguments. * @param primarySources the primary sources to load * @param args the application arguments (usually passed from a Java main method) * @return the running {@link ApplicationContext} */ public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
//首先创建一个Spring应用,然后执行run方法。 return new SpringApplication(primarySources).run(args); }
进入new SpringApplication(primarySources)
/** * Create a new {@link SpringApplication} instance. The application context will load * beans from the specified primary sources (see {@link SpringApplication class-level} * documentation for details. The instance can be customized before calling * {@link #run(String...)}. * @param resourceLoader the resource loader to use * @param primarySources the primary bean sources * @see #run(Class, String[]) * @see #setSources(Set) */ @SuppressWarnings({ "unchecked", "rawtypes" }) public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//判断是不是web应用 this.webApplicationType = WebApplicationType.deduceFromClasspath();
//得到所有的META_INF下的spring.factories里面配置的ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//得到所有的META_INF下的spring.factories里面配置的ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//得到主类
this.mainApplicationClass = deduceMainApplicationClass(); }
然后再进入ru/**
* Run the Spring application, creating and refreshing a new * {@link ApplicationContext}. * @param args the application arguments (usually passed from a Java main method) * @return a running {@link ApplicationContext} */ public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty();
//得到META_INF下的spring.factoies下的SpringApplicationRunListeners SpringApplicationRunListeners listeners = getRunListeners(args);
//执行每一个SpringApplicationRunListener的starting方法 listeners.starting(); try {
//封装命令行参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
/**
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
//这里会调用SpringApplicationRunListener的environmentPrepared方法
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}*/
configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment);
//创建ioc容器 context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
/**
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
postProcessApplicationContext(context);
//执行ApplicationContextInitializer的initializers方法
applyInitializers(context);
//执行SpringApplicationRunListener的contextPrepared方法
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
//执行SpringApplicationRunListener的contextLoaded方法
listeners.contextLoaded(context);
}
*/
//扫描,创建,加载所有组件的地方;(配置类,组件,自动配置),嵌入式sevlet容易在此创建
refreshContext(context);
//回调ApplicationRunner和CommandLineRunner,这两个类不需要配置在spring.factoies中,直接放在ioc容器中就可以 afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); }
//执行SpringApplicaitonRunListener的started方法 listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try {
//执行SpringApplicationRunListener的running方法 listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); }
//返回已经启动的ioc容器 return context; }