Spring Boot版本为2.6.0
一、从main函数开始public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
SpringApplication的静态run方法
public static ConfigurableApplicationContext run(Class> primarySource, String... args) {
return run(new Class>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class>[] primarySources, String[] args) {
// 新建一个SpringApplicaton实例,先执行构造函数然后在执行非静态的run方法。
return new SpringApplication(primarySources).run(args);
}
新建一个SpringApplicaton实例,先执行构造函数,然后在执行非静态的run方法。
二、SpringApplication的构造方法SpringApplication的构造方法进行的一系列操作
-
设置类装载器
-
设置引导程序注册的初始化器
-
设置容器的初始化类器
-
设置监听器类实例
public SpringApplication(Class>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new linkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 根据Java虚拟机栈的入栈的方法寻找main方法,返回main方法的class对象
this.mainApplicationClass = deduceMainApplicationClass();
}
spring.factories文件内容(spring-boot-2.6.0.jar包meta-INF目录下的,其他spring-boot-xxx.jar包也有)
# Logging Systems org.springframework.boot.logging.LoggingSystemFactory= org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory, org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory, org.springframework.boot.logging.java.JavaLoggingSystem.Factory # PropertySource Loaders org.springframework.boot.env.PropertySourceLoader= org.springframework.boot.env.PropertiesPropertySourceLoader, org.springframework.boot.env.YamlPropertySourceLoader # ConfigData Location Resolvers org.springframework.boot.context.config.ConfigDataLocationResolver= org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver, org.springframework.boot.context.config.StandardConfigDataLocationResolver # ConfigData Loaders org.springframework.boot.context.config.ConfigDataLoader= org.springframework.boot.context.config.ConfigTreeConfigDataLoader, org.springframework.boot.context.config.StandardConfigDataLoader # Run Listeners org.springframework.boot.SpringApplicationRunListener= org.springframework.boot.context.event.EventPublishingRunListener # Error Reporters org.springframework.boot.SpringBootExceptionReporter= org.springframework.boot.diagnostics.FailureAnalyzers # Application Context Initializers org.springframework.context.ApplicationContextInitializer= org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer, org.springframework.boot.context.ContextIdApplicationContextInitializer, org.springframework.boot.context.config.DelegatingApplicationContextInitializer, org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer, org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer # Application Listeners org.springframework.context.ApplicationListener= org.springframework.boot.ClearCachesApplicationListener, org.springframework.boot.builder.ParentContextCloserApplicationListener, org.springframework.boot.context.FileEncodingApplicationListener, org.springframework.boot.context.config.AnsiOutputApplicationListener, org.springframework.boot.context.config.DelegatingApplicationListener, org.springframework.boot.context.logging.LoggingApplicationListener, org.springframework.boot.env.EnvironmentPostProcessorApplicationListener # Environment Post Processors org.springframework.boot.env.EnvironmentPostProcessor= org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor, org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor, org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor, org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor, org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor, org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor # Failure Analyzers org.springframework.boot.diagnostics.FailureAnalyzer= org.springframework.boot.context.config.ConfigDataNotFoundFailureAnalyzer, org.springframework.boot.context.properties.IncompatibleConfigurationFailureAnalyzer, org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.MutuallyExclusiveConfigurationPropertiesFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer, org.springframework.boot.diagnostics.analyzer.PatternParseFailureAnalyzer, org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer # Failure Analysis Reporters org.springframework.boot.diagnostics.FailureAnalysisReporter= org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter # Database Initializer Detectors org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector= org.springframework.boot.flyway.FlywayDatabaseInitializerDetector, org.springframework.boot.jdbc.AbstractDataSourceInitializerDatabaseInitializerDetector, org.springframework.boot.jdbc.init.DataSourcescriptDatabaseInitializerDetector, org.springframework.boot.liquibase.LiquibaseDatabaseInitializerDetector, org.springframework.boot.orm.jpa.JpaDatabaseInitializerDetector, org.springframework.boot.r2dbc.init.R2dbcscriptDatabaseInitializerDetector # Depends On Database Initialization Detectors org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector= org.springframework.boot.sql.init.dependency.AnnotationDependsOnDatabaseInitializationDetector, org.springframework.boot.jdbc.SpringJdbcDependsOnDatabaseInitializationDetector, org.springframework.boot.jooq.JooqDependsOnDatabaseInitializationDetector, org.springframework.boot.orm.jpa.JpaDependsOnDatabaseInitializationDetector
三、SpringApplication实例的run()方法(非静态run方法)
public ConfigurableApplicationContext run(String... args) {
// 开始计时:返回正在运行的Java虚拟机的当前值
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(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);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timetakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
// 监听器开始工作
listeners.ready(context, timetakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
四、SpringApplication实例的prepareContext()方法
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 设置配置环境
context.setEnvironment(environment);
// 后置处理应用上下文
postProcessApplicationContext(context);
applyInitializers(context);
// 会按优先级顺序遍历执行SpringApplicationRunListener的contextPrepared方法
listeners.contextPrepared(context);
// 关闭bootstrapContext
bootstrapContext.close(context);
if (this.logStartupInfo) {
// 启动信息输出到控制台
logStartupInfo(context.getParent() == null);
// 活动配置文件信息输出到控制台
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
// 获取应用上下文的内部bean工厂
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// applicationArguments注册为单例,bean的ID为springApplicationArguments
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
// printedBanner注册为单例,bean的ID为springBootBanner
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory) {
// 设置bean定义信息是否允许覆盖,this.allowBeanDefinitionOverriding默认为false
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
// 根据this.lazyInitialization布尔值,是否添加懒加载bean工厂后置处理器
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
// 获取bean,为SpringApplication.run(SpringBootShiroApplication.class, args)中这里传的class
Set
五、SpringApplication实例的refreshContext()方法
private void refreshContext(ConfigurableApplicationContext context) {
if (this.registerShutdownHook) {
// 一个Runnable,用作一个关闭钩子,用于优雅地关闭Spring Boot应用程序
shutdownHook.registerApplicationContext(context);
}
refresh(context);
}
以下是调用AbstractApplicationContext类的refresh()方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
prepareRefresh();
// 获取刷新后的bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备bean工厂,配置bean工厂属性
prepareBeanFactory(beanFactory);
try {
// 设置bean工厂的后置处理
postProcessBeanFactory(beanFactory);
// 开始ng.context.beans.post-process步骤
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 调用在上下文中注册为bean工厂后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册拦截bean创建的bean后置处理器
registerBeanPostProcessors(beanFactory);
// spring.context.beans.post-process步骤结束
beanPostProcess.end();
// 初始化MessageSource,国际化处理
initMessageSource();
// 初始化事件
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// 注册监听器们
registerListeners();
// 完成此上下文的bean工厂的初始化,初始化所有剩余的单例bean。
finishBeanFactoryInitialization(beanFactory);
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();
}
}
}



