提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
springboot2.5.6版本
入口
public static void main(String[] args) {
SpringApplication.run(KafkaMain.class, args);
}
一、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.获取应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//2.加载META-INF/spring.factories下所有的 BootstrapRegistryInitializer
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
//3.加载META-INF/spring.factories下所有的 ApplicationContextInitializer 初始化器
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//4.加载META-INF/spring.factories 下所有的 ApplicationListener 监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//5.检查启动类
this.mainApplicationClass = deduceMainApplicationClass();
}
我需要了解spring内置注入的这些类是做什么的:
BootstrapRegistryInitializer
ApplicationContextInitializer
添加的初始化器
ApplicationListener
添加的监听器
二 run
//运行 Spring 应用程序,创建并刷新一个新的ApplicationContext
public ConfigurableApplicationContext run(String... args) {
//记录程序运行时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
//ConfigurableApplicationContext Spring 的上下文
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
//加载META-INF/spring.factories下所有的 SpringApplicationRunListene
SpringApplicationRunListeners listeners = getRunListeners(args);
//发布应用启动事件 触发LoggingApplicationListener监听器
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//存储args
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, 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);
//容器刷新完成 回调ApplicationRunner CommandLineRunner
callRunners(context, applicationArguments);
} catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
} catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
三 prepareEnvironment()
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// 获取或者创建 environment。这里获取类型是 StandardServletEnvironment
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 将入参配置到环境配置中
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
//发布环境准备时间ApplicationEnvironmentPreparedEvent, 触发EnvironmentPostProcessorApplicationListener监听器
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
"Environment prefix cannot be set via properties.");
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
四 prepareContext()
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//设置环境
context.setEnvironment(environment);
postProcessApplicationContext(context);
//应用 SpringApplication 构造器中加载的ApplicationContextInitializer
applyInitializers(context);
//发布 容器 初始化完成事件ApplicationContextInitializedEvent,bean定义被加载之前
listeners.contextPrepared(context);
bootstrapContext.close(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 这里将启动类加入到 beanDefinitionMap 中,为后续的自动化配置做好了基础
load(context, sources.toArray(new Object[0]));
//发布应用准备事件ApplicationPreparedEvent
listeners.contextLoaded(context);
}