SpringApplication 运行及源码解读
SpringApplication.run
@SpringBootApplication
public class AdvancedApplication {
public static void main(String[] args) {
SpringApplication.run(AdvancedApplication.class, args);
}
}在使用SpringBoot时,上面的代码我们一定很熟悉,这样写我们的程序就会自动创建并允许,但是Spring具体为我们做了什么我们就不得而知, 接下来我们就来阅读一下源码来一探究竟
源码分析
对于这段代码官方的解释是: Run the Spring application, creating and refreshing a new 大意为:运行Spring应用程序,创建并刷新一个新的
public ConfigurableApplicationContext run(String... args) {
//1.
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//2.
configureHeadlessProperty();
//3.
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//4.
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
//5.
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//6.
context = createApplicationContext();
//7.
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//8.
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//9.
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}1.
stopWatch.start();这里只是为了记录创建完成启动Spring所需要的时间,如:Started XXXApplication in 3.82 seconds (JVM running for 6.336)2.通过
configureHeadlessProperty()配置属性
3.通过
getRunListeners()实例化监听器
这里请注意看 SpringApplicationRunListeners 与 SpringApplicationRunListener,这时连个类,前者是后者的一个集合, 这时我们需在看getSpringFactoriesInstances()方法
如果您看过 EnableAutoConfiguration 源码解析 ,您很快就会明白他做了什么,这里主要是SpringFactoriesLoader.loadFactoryNames 是将spring.factories文件中的key存放在List中,在通过createSpringFactoriesInstances实例化 通过spring.factories 我们可以看出最终实例化的是 EventPublishingRunListener, 然后在进行 listeners.starting();来发送事件, 这里的starting()是调用的EventPublishingRunListener,当我查看其内部方法是,在实例化时又会预加载了ApplicationListener spring.factories 文件
4.prepareEnvironment 配置环境
首先会通过(1)getOrCreateEnvironment()等方法创建和配置环境,(2)发布一个ApplicationEnvironmentPreparedEvent监听,代码如下,具体发布的内容,大家可以追踪一下
bindToSpringApplication进行了对spring.main的绑定,完成配置环境
5.通过
configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment)配置忽略一些bean,以及启动时的Banner6.创建
ConfigurableApplicationContext7.
getSpringFactoriesInstances我们发现最终又是通过loadSpringFactories()方法读取spring.factories文件8.接下来我们继续查看
prepareContext()
首先配置一个环境信息,之后会通过isteners.contextPrepared(context);发送ApplicationContextInitializedEvent
接下获取启动类,并将其作为bean加载到Spring 容器中,再通过 listeners.contextLoaded(context); 发送 ApplicationPreparedEvent
9.
refresh()方法,我们追踪代码会发现,最终走的是AbstractApplicationContext下方的代码 这个方法做了很多,如: 完成beanFactory设置, invokeProcessBeanFactory,国际化信息等,关于refresh()更多信息,请点击这里refresh源码解析
到这SpringBoot项目就完车了启动,最后callRunners()方法,这是我们经常用到的,当项目启动后区做一些处理,获取实现ApplicationRunner CommandLineRunner这两个接口
Last updated
Was this helpful?