SpringBoot启动流程
SpringBoot启动过程
- 生成一个SpringApplication对象
- webApplicationType(推断web应用类型,NONE、REACTIVE、SERVLET)
- 从spring.factories中获取BootstrapRegistryInitializer对象
- initializers = 从spring.factories中获取ApplicationContextInitializer对象
- listeners = 从spring.factories中获取ApplicationListener对象
- SpringApplication对象的Run方法
- 获取SpringApplicationRunListener--->EventPublishingRunListener
- SpringApplicationRunListener.starting() 容器处理开始创建状态
- 创建一个Spring容器
- ApplicationContextInitializer--->初始化Spring容器
- SpringApplicationRunListener.contextPrepared()
- 把传给run方法的配置类注册成为一个Bean
- SpringApplicationRunListenner.contextLoaded()
- 会解析配置类、扫描、启动tomcat/jetty
- SpringApplicationRunListener.started()
- SpringApplicationRunListener.ready()
- run方法启动时传入了当前类 ContractApplication.class,传入当前类的作用主要是为了解析当前类上面的注解(不一定传递当前类,也可以自己写一个类,在写的类上添加对应的注解)
@SpringBootApplication
@ComponentScan("com.example")
public class ContractApplication {
public static void main(String[] args) {
SpringApplication.run(ContractApplication.class);
}
}
- 将传入的类封装成一个Class类型的数组
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
- 生成一个SpringApplication对象,在调用SpringApplication的run方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
- new SpringApplication()构造方法,主要是给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));
//1.推测项目的应用类型(通过项目目录结构,和类),NONE(不是Web项目),REACTIVE(Web应用,响应式),SERVLET(Web应用,springmvc)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//2.从spring.factories中获取需要加载的BootstrapRegistryInitializer类型的的实现类
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
//3.从spring.factories中获取需要加载的AppliationContextInitializer(初始化器)类型的实现类
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//4.从spring.factories中获取需要加载的ApplicationListener(应用监听器)类型的实现类
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//5.推测出Main类(main()方法所在的类)
this.mainApplicationClass = deduceMainApplicationClass();
}
- spring.factories
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
- SpringApplication.run()
public ConfigurableApplicationContext run(String... args) {
//记录开始启动的时间
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
//定义了一个Spring容器
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
//从spring.factories中获取SpringApplicationRunListener对象
//默认会拿到一个EventPublishingRunListener,它会启动过程的各个阶段发布对应的事件(运行监听器)
SpringApplicationRunListeners listeners = getRunListeners(args);
//执行RunListener的start方法
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//将run()的参数封装为DefaultApplicatoinArguments对象
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//配置环境,properties文件的配置,setvlet,jvm环境配置等,封装成ConfigurableEnvironment
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
//打印spirngboot启动banner
Banner printedBanner = printBanner(environment);
//根据应用类型创建Spring容器
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
//使用初始化器初始化Spring容器
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//刷新Spring容器,会解析配置类,扫描 启动WebServer
refreshContext(context);
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
//spring容器状态为started
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);
//spring容器状态为ready
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
自动配置原理
-
@SpringApplication
- @EnableAutoConfiguration
- @Import(AutoConfigurationImportSelector.class)
- @Import(AutoConfigurationImportSelector.class)
- @EnableAutoConfiguration
-
AutoConfigurationImportSelector.java
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//会在所有@Configuration都解析完了之后才执行
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//获取自动配置类(spirng.factories中导入)
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
- getAutoConfigurationEntry()
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//获取@EnableAutoConfiguration的属性
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取spring.factories中所有的AutoConfiguration
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//去重
configurations = removeDuplicates(configurations);
//获取需要排除的AutoConfiguration @EnableAutoConfiguation注解的exclude属性设置
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//过滤
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
//最后返回的AutoConfiguration都是符合条件的
return new AutoConfigurationEntry(configurations, exclusions);
}