直接从 SpringBoot 程序入口的 run
方法看起:
// org.springframework.boot.SpringApplication#run(java.lang.Object, java.lang.String...)
public static ConfigurableApplicationContext run(Object source, String... args) {
return run(new Object[] { source }, args);
}
执行第 run(new Object[] { source }, args)
方法:
// org.springframework.boot.SpringApplication#run(java.lang.Object[], java.lang.String[])
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
可以看到,这里启动实际上是分为两步,先是创建 SpringApplication
对象,然后执行该对象的 run
方法。下面根据这两步进行深入:
创建 SpringApplication 对象
下一步会进入 SpringApplication
类的构造方法:
// org.springframework.boot.SpringApplication#SpringApplication(java.lang.Object...)
public SpringApplication(Object... sources) {
initialize(sources);
}
接着进入 initialize
方法:
// org.springframework.boot.SpringApplication#initialize
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
// 保存配置类,包含入口类
this.sources.addAll(Arrays.asList(sources));
}
// 判断当前是否是一个 web 应用
this.webEnvironment = deduceWebEnvironment();
// 从类路径下找到 META-INF/spring.factories 配置的所有 ApplicationContextInitializer 类并反射创建实例并保存到当前 SpringApplication 实例的 initializers 属性
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 从类路径下找到 META-INF/spring.factories 配置的所有 ApplicationListener 类并反射创建实例保存到当前 SpringApplication 实例的 listeners 属性
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 从调用栈中获取到执行了 main 方法的配置类即入口类保存到当前 SpringApplication 实例的 mainApplicationClass 属性
this.mainApplicationClass = deduceMainApplicationClass();
}
在创建 SpringApplication
对象的过程中实例化了类路径下 META-INF/spring.factories
中 ApplicationContextInitializer
节对应的应用上下文初始化器类和 ApplicationListener
节对应的应用监听器类并保存到了 SpringApplication
对象中。
可以看到在很多包中都有这个文件,下面为自动配置包中的 spring.factories
文件:
# spring-boot-autoconfigure-1.5.19.RELEASE.jar!/META-INF/spring.factories
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer
# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider
执行 SpringApplication.run()
执行 org.springframework.boot.SpringApplication#run(java.lang.String...)
方法:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 声明一个 IoC 容器
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
// AWT 相关
configureHeadlessProperty();
// 通过 getSpringFactoriesInstances 从类路径下找到 META-INF/spring.factories 配置的所有 SpringApplicationRunListener 类并反射创建实例返回
SpringApplicationRunListeners listeners = getRunListeners(args);
// 回调执行所有 SpringApplicationRunListener 实例的 starting 方法
listeners.starting();
try {
// 封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 准备环境,创建环境完成后在该方法中又回调执行了所有 SpringApplicationRunListener 实例的 environmentPrepared 方法,表示环境准备完成
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
// 控制台打印 SpringBoot 图标
Banner printedBanner = printBanner(environment);
// 根据当前环境的不同创建不同类型的 IoC 容器
context = createApplicationContext();
// 初始化异常分析器
analyzers = new FailureAnalyzers(context);
// 准备上下文环境:
// 1、将 environment 保存到了 context 即 IoC 容器中
// 2、通过 applyInitializers(context) 方法,执行了所有 ApplicationContextInitializer 实例的 initialize(context) 方法(这些 ApplicationContextInitializer 实例是在初始化 SpringApplication 实例时创建保存的)
// 3、还会回调执行所有 SpringApplicationRunListener 实例的 contextPrepared(context) 方法
// 4、在 prepareContext 方法最后一行还会回调执行所有 SpringApplicationRunListener 实例的 contextLoaded(context) 方法
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// 刷新 IoC 容器,IoC 容器初始化,扫描、创建、加载所有组件(配置类、自动配置功能),如果是 web 应用,在这一步还会创建嵌入式 Servlet 容器
refreshContext(context);
// 刷新后处理,会通过 callRunners(context, args) 方法从 IoC 容器中获取所有 ApplicationRunner 和 CommandLineRunner 的 bean,并回调它们的 run 方法
afterRefresh(context, applicationArguments);
// 回调执行所有的 SpringApplicationRunListener 实例的 finished 方法,表示应用启动完成
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
// 整个 SpringBoot 应用启动完成后返回 IoC 容器
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
小结
在 SpringBoot 应用启动的过程中会回调一些我们预配置组件的指定方法,这些组件可以是我们配置在指定文件中的类,也可以是我们注册到 IoC 容器的 bean。分类如下:
配置在 META-INF/spring.factories
中:
org.springframework.context.ApplicationContextInitializer
org.springframework.context.ApplicationListener
org.springframework.boot.SpringApplicationRunListener
注册在 IoC 容器中:
org.springframework.boot.ApplicationRunner
org.springframework.boot.CommandLineRunner
它们执行方法回调顺序如下:
SpringApplicationRunListener.starting()
SpringApplicationRunListener.environmentPrepared()
ApplicationContextInitializer.initialize()
SpringApplicationRunListener.contextPrepared()
SpringApplicationRunListener.contextLoaded()
ApplicationRunner.run()
CommandLineRunner.run()
SpringApplicationRunListener.finished()
评论区