main入口
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
// 执行SpringAppllication的静态run方法
SpringApplication.run(MyApplication.class, args);
}
}
在Application的静态run方法内创建了SpringApplication实例,并调用了实例方法run
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
// 首先,创建SpringApplication实例
return new SpringApplication(primarySources)
// 然后,调用其run方法
.run(args);
}
SpringApplication的实例化
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 资源加载器
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 推断当前应用程序的类型
// 是Servlet? 还是Reactive?
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 从META-INF/spring.factories中加载BootstrapRegistryInitializer的实例
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
// 从META-INF/spring.factories中加载ApplicationContextInitializer的实例
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 从META-INF/spring.factories中加载ApplicationListener的实例
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 推断main方法所在的类
this.mainApplicationClass = deduceMainApplicationClass();
}
调用SpringApplication实例的run方法
public ConfigurableApplicationContext run(String... args) {
SpringApplicationHooks.hooks().preRun(this);
long startTime = System.nanoTime();
// 引导器 上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 配置Headless属性
configureHeadlessProperty();
// 从META-INF/spring.factories中加载SpringApplicationRunListener的实例,并封装到SpringApplicationRunListeners对象当中
SpringApplicationRunListeners listeners = getRunListeners(args);
// 监听器广播事件:开始启动中
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 将运行参数 封装进ApplicationArguments中
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备 Environment
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
// 打印Banner
Banner printedBanner = printBanner(environment);
// 创建 应用上下文。若是Servlet应用,则返回AnnotationConfigSerlvetWebServerApplicationContext的实例。
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 准备 应用上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
if (refreshContext(context)) { // 刷新Context,若执行刷新成功,则返回true
// 在Context刷新后,默认是空方法
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(),
timeTakenToStartup);
}
// 广播事件:已启动
listeners.started(context, timeTakenToStartup);
// 调用 Runner,包括CommandLineRunner和ApplicationRunner的实例
callRunners(context, applicationArguments);
}
}
catch (Throwable ex) {
// 处理异常
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
SpringApplicationHooks.hooks().postRun(this, context);
return context;
}
内置Tomcat(Jetty、undertow等)启动
创建ApplicationContext对象。
在run方法中,以下行创建了ApplicationContext对象。
// 创建 应用上下文。若是Servlet应用,则返回AnnotationConfigSerlvetWebServerApplicationContext的实例。
context = createApplicationContext();
实际返回的 是 ApplicationContext的子类AnnotationConfigServletWebServerApplicationContext的实例
调用ApplicationContext的refresh()
创建AppliationContext之后,在run方法中,执行了refreshContext方法
if (refreshContext(context)) { // 刷新Context,若执行刷新成功,则返回true
进入refreshContext,跟踪后,发现最终调用了ApplicationContext的refresh方法
protected void refresh(ConfigurableApplicationContext applicationContext) {
// 调用ApplicationContext的refresh方法
applicationContext.refresh();
}
下面先看下 AnnotationConfigServletWebServerApplicationContext的继承结构
refresh方法是由其父类 AbstractApplicationContext实现的。
下面的refresh()方法,重点关注方法中的 onRefresh()那一行
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 为刷新做一些准备工作
prepareRefresh();
// 获取一个新鲜的BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 为BeanFactory的使用做一些准备工作
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 留给子类,对BeanFactory作工作
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
// 调用BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// =========== 注意:为子类准备的方法,用于初始化特殊的bean
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) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
而AnnotationConfigServletWebServerApplicationContext的直接父类ServletWebServerApplicationContext重写了onRefresh方法
调用onRefresh方法
createWebServer()
可以看到,其中的createWebServer()便是用于创建及启动内嵌Tomcat的了~~