1. Spring Boot启动类的@SpringBootApplication注解
@SpringBootApplication
注解是一个组合注解,主要有以下三个:
-
@SpringBootConfiguration
:表示一个类提供了Spring Boot的配置。 -
@ComponentScan
:定义 Spring 扫描的包,它默认会扫描标注为Spring Bean的类,并实例化这些组件到 SpringIOC 容器中。 -
@EnableAutoConfigration
:核心注解——自动配置包,它会获取主程序类所在的包路径,并将包路径(包括子包)下的所有组件注册到 SpringIOC 容器中。
2. SpringApplication.run(DemoApplication.class, args)
直接看源码吧
// 0. 调用 SpringApplication.run(...)静态方法后,它会new一个SpringApplication去调用真正的run方法。
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 1. 初始化监听器并启动,Spring容器的启动都是从监听器开始的,就像Spring4需要配置xml的时候也是首先在web.xml中配置Spring的监听器
// 2. 然后这里会发布ApplicationStartedEvent事件。
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 3. 接着进入一个大try-catch,平时开发时遇到Spring Boot启动失败却没有打印出错误信息,我就会把断点打在这里dubug。
// 4. Try里面第一步时装配参数和环境,选择对的profile
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 5. 装配完环境后会触发ApplicationEnvironmentPreparedEvent事件
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
// 6. 接着就会打印Banner(外国人的开源项目都喜欢这样,redis也会打印他的图标。)
Banner printedBanner = printBanner(environment);
// 7. 然后会根据是否web环境创建Spring的应用上下文
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 8. 创建好后就装配应用上下文
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// 9. 接着刷新上下文,(刷新结束后调用afterRefresh方法,这是个空实现,猜测是个钩子方法)
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
// 10. 刷新结束后会发布ApplicationReadyEvent事件
listeners.started(context);
// 11. 然后会调用自定的Runner。(这些Runner 用在 SpringApplication启动后运行一些特殊代码)
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;
}