SpringBoot 启动过程和自动装配
SpringBoot启动过程
- SpringBoot启动注解了@SpringBootApplication 的 xxxApplication的main方法中,SpringApplication.run(DemoApplication.class, args)这个是启动的开始位置。主要分为两个步骤:
- 1、SpringApplication初始化META_INF/spring.factories中11个ApplicationListener类型的Listener对象和 7个ApplicationContextInitializer类型的Initializer对象。
- 2、SpringApplication对象run()方法完成SpringBoot的启动过程。SpringBoot的启动过程有7中状态:ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationContextInitializedEvent、ApplicationPreparedEvent、ApplicationStartedEvent、ApplicationReadyEvent和ApplicationFailedEvent。通过观察者模式,当有状态事件发生时,触发11个ApplicationListener中能够处理的Listener进行事件处理。SpringBoot的启动过程主要分为:1)配置环境变量(系统环境变量、配置文件参数);2)打印启动的banner信息;3)创建webApplicationType类型的Context(SERVLET、REACTIVE、 NONE);4)调用applyInitializers()进行7个ApplicationContextInitializer对象进行初始化添加3个Processor(CachingMetadataReaderFactoryPostProcessor、ConfigurationWarningsPostProcessor、PropertySourceOrderingPostProcessor和Listener添加,以及其他初始化操作,打印starting启动日志,beanFactory load SpringBootApplication的SpringBoot启动类,向beanFactory 注册到beanDefinitionMap中;5)调用spring AbstractApplicationContext refresh进行类的加载
context进行简单的属性初始化准备下环境;6)打印服务启动的时间的日志。具体流程见图: - 3启动流程的关键源码:
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();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>. ();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new
DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters =
getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
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;
}
SpringBoot自动装配过程
- Springboot启动过程主要有完成自动装配关键地方:prepareContext(context, environment, listeners, applicationArguments, printedBanner)和refreshContext(context)中调用PostProcessorRegistrationDelegate中的invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) 方法。prepareContext方法完成SpringBoot项目的xxxApplication的BeanDefinition的注册;refreshContext通过spring的注解扫描完成自动装配。
- Spring的注解扫描完成自动装配过程中,doProcessConfigurationClass方法完成@ComponentScan、@Import、@PropertySource、@ImportResource和@Bean的扫描,扫描SpringBootApplication会扫描出@SpringBootApplication注解继承过来两个对象:AutoConfigurationImportSelector 和 AutoConfigurationPackages.Registrar。AutoConfigurationImportSelector对象完成从spring.factories文件中加载EnableAutoConfiguration对象。
- 流程中核心代码
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
|