springboot 通过SpringApplication.run的方式启动,在启动时通过构造函数初始化容器类型
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//获取容器类型 REACTIVE SERVLET NONE 三种类型 一般web服务为 SERVLET 类型
this.webApplicationType = deduceWebApplicationType();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
在SpringApplication中的 run(String… args)方法中完成spring容器的启动
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);
//获取配置文件 准备应用中用到的参数 默认读取classPath路径下的
//application.properties 和bootStrap.yml文件
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//创建spring容器的上下文
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//刷新spring的上下文 此方法中完成bean的初始化及bean的ioc
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;
}
向spring容器注册bean的调用栈
1: SpringApplication.run(String[] args)
=>refreshContext(context)
2: AbstractApplicationContext.refresh()
=>invokeBeanFactoryPostProcessors(beanFactory)
=>PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
3: PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
=>invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
=>postProcessor.postProcessBeanDefinitionRegistry(registry);
4: ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry =>processConfigBeanDefinitions(registry)
=>parser.parse(candidates);
//扫描路径的下的文件 spring的注解的扫描 在此处完成并注册到beanFactroy中
5: ConfigurationClassParser.parse(Set<BeanDefinitionHolder> configCandidates)
=>parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
=>processConfigurationClass(ConfigurationClass configClass)
=>doProcessConfigurationClass(configClass, sourceClass)//