Spring 应用的启动类。
【资料图】
二、SpringApplication 执行了什么?创建 ApplicationContext 实例
ApplicationContext 就是我们所说的容器实例。
注册 CommandLinePropertySource
CommandLinePropertySource 的作用是将命令行参数输出为 Spring 属性。
刷新 ApplicationContext
这一步骤包括诸多操作,并且会加载所有的单例 bean。
触发 CommandLineRunner bean
CommandLineRunner 是一个接口,它只有一个 run() 方法。
凡是实现了此接口的类,如果被加载进容器,就会执行其 run() 方法。
容器中可以包含多个实现 CommandLineRunner 的 bean,执行顺序可以遵从 Ordered 接口或者 @Order 注解设置。
三、bean 加载源SpringApplication 有诸多 bean 加载源:
AnnotatedBeanDefinitionReader
顾名思义,注解 bean 定义读取。
XmlBeanDefinitionReader
xml 配置资源读取。
ClassPathBeanDefinitionScanner
classpath 路径扫描。
GroovyBeanDefinitionReader
... ...
四、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));this.webApplicationType = WebApplicationType.deduceFromClasspath();this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();}
1、resourceLoader参数可以为 null,为 null 时,使用默认:
(this.resourceLoader != null) ? this.resourceLoader: new DefaultResourceLoader(null);
2、primarySources主要的 bean 定义来源。
3、webApplicationTypeweb 应用类型判断:
NONE:应用不会以 web 应用运行,且不会启动内嵌 web 服务器。
SERVLET:基于 servlet web 应用,运行于内嵌 web 服务器。
REACTIVE:响应式 web 应用,运行于内嵌 web 服务器。
4、bootstrapRegistryInitializersBootstrapRegistryInitializer:回调接口,用于 BootstrapRegistry 初始化。
BootstrapRegistry:对象注册器,作用期间为从应用启动,Environment 处理直到 ApplicationContext 完备。
5、setInitializersApplicationContextInitializer 列表设置。
ApplicationContextInitializer:回调接口,用于 Spring ConfigurableApplicationContext 初始化。
通常用于 web 应用 ApplicationContext 自定义初始化。如注册 property source、激活 profile 等。
6、setListenersApplicationListener 列表设置。
ApplicationListener:应用事件监听接口,基于标准的 EventListener 接口,观察者模式实现。
7、mainApplicationClassmain class
五、SpringApplication.run() 逻辑public ConfigurableApplicationContext run(String... args) {long startTime = System.nanoTime();DefaultBootstrapContext bootstrapContext = createBootstrapContext();ConfigurableApplicationContext context = null;configureHeadlessProperty();SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting(bootstrapContext, this.mainApplicationClass);try {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);Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);}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);listeners.ready(context, timeTakenToReady);}catch (Throwable ex) {handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}return context;}
创建,刷新 ApplicationContext 并运行 Spring 应用。
1、startTime使用 System.nanoTime(),计算耗时间隔更精确。不可用于获取具体时刻。
2、创建启动上下文DefaultBootstrapContext = createBootstrapContext();
BootstrapContext:启动上下文,生命周期同 BootstrapRegistry。
DefaultBootstrapContext 继承了 BootstrapContext、BootstrapRegistry。
用于 BootstrapRegistry 初始化。
3、ConfigurableApplicationContext可配置的 ApplicationContext。
4、获取事件监听器SpringApplicationRunListeners = getRunListeners()。
Spring 应用运行期间事件监听。
5、starting 事件listeners.starting():starting step。
6、启动参数处理ApplicationArguments:提供 SpringApplication 启动参数访问。
7、应用环境配置ConfigurableEnvironment = prepareEnvironment()
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {// Create and configure the environmentConfigurableEnvironment environment = getOrCreateEnvironment();configureEnvironment(environment, applicationArguments.getSourceArgs());ConfigurationPropertySources.attach(environment);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) {EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());}ConfigurationPropertySources.attach(environment);return environment;}
configureEnvironment() 模板方法,代理执行 configurePropertySources() 及 configureProfiles() 方法。
configurePropertySources():PropertySource 配置,用于添加、移除或者调序 PropertySource 资源。CommandLinePropertySource 在这一步处理。
configureProfiles():应用 profile 设置。
ConfigurationPropertySources.attach(environment)
ConfigurationPropertySources:提供对 ConfigurationPropertySource 的访问。
attach(environment):就是将这个功能提供给 environment。
listeners.environmentPrepared(bootstrapContext, environment)
environment-prepared step。
DefaultPropertiesPropertySource.moveToEnd(environment)
DefaultPropertiesPropertySource:是一个 MapPropertySource,包含 SpringApplication 可以使用的一些默认属性。为了使用方便,默认会置于尾序。
bindToSpringApplication(environment)
将 environment 绑定到 SpringApplication。
Binder:用于对象绑定的容器。
8、configureIgnoreBeanInfo()9、打印 BannerprintBanner()。
10、创建 ApplicationContextcreateApplicationContext()。
内部通过 ApplicationContextFactory 创建。
ApplicationContextFactory:策略接口,默认实现为 DefaultApplicationContextFactory。
11、ApplicationStartup 设置为容器设置 ApplicationStartup,用于记录启动过程性能指标。
12、ApplicationContext 准备prepareContext()
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {context.setEnvironment(environment);postProcessApplicationContext(context);applyInitializers(context);listeners.contextPrepared(context);bootstrapContext.close(context);if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// Add boot specific singleton beansConfigurableListableBeanFactory beanFactory = context.getBeanFactory();beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}}if (this.lazyInitialization) {context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());}context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));// Load the sourcesSet
设置环境
postProcessApplicationContext() 前置处理
beanNameGenerator 设置,用于 bean 名称生成。
resourceLoader 设置,用于资源加载。
addConversionService:ConversionService 类型转换 Service。
applyInitializers()
ApplicationContextInitializer 应用
contextPrepared 事件
【spring.boot.application.context-prepared】step
BootstrapContext 关闭
注册 springApplicationArguments bean
注册 springBootBanner bean
AbstractAutowireCapableBeanFactory
设置是否允许 bean 之间的循环依赖,并自动处理,默认为 true。
设置是否允许 bean 定义覆盖,默认为 true。
lazyInitialization 懒加载
设置 LazyInitializationBeanFactoryPostProcessor post-processor。
PropertySource 重排序
设置 PropertySourceOrderingBeanFactoryPostProcessor post-processor。
getAllSources() bean 定义源加载
load() bean 定义加载,BeanDefinitionLoader
用于从底层资源加载 bean 定义信息,包括 xml、JavaConfig。
是基于 AnnotatedBeanDefinitionReader、XmlBeanDefinitionReader、ClassPathBeanDefinitionScanner 的门面模式。
beanNameGenerator、resourceLoader、environment 设置。
资源加载:
private void load(Object source) { Assert.notNull(source, "Source must not be null"); if (source instanceof Class>) { load((Class>) source); return; } if (source instanceof Resource) { load((Resource) source); return; } if (source instanceof Package) { load((Package) source); return; } if (source instanceof CharSequence) { load((CharSequence) source); return; } throw new IllegalArgumentException("Invalid source type " + source.getClass()); }
contextLoaded() contextLoaded 事件
【spring.boot.application.context-loaded】step。
13、ApplicationContext 刷新refreshContext()
注册 shutdownHook。
Runtime.getRuntime().addShutdownHook(new Thread(this, "SpringApplicationShutdownHook"));
刷新操作:加载或刷新
AbstractApplicationContext::refresh()public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);beanPostProcess.end();// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset "active" flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring"s core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();contextRefresh.end();}}}
作为启动方法,如果失败,则必须销毁所有已创建的单例bean。
StartupStep【spring.context.refresh】
准备刷新 prepareRefresh()
设置启动日期。
设置 active 标志。
initPropertySources():子类实现 PropertySource 初始化。
validateRequiredProperties():校验 ConfigurablePropertyResolver#setRequiredProperties 设置的必需属性。
obtainFreshBeanFactory():通过子类获取最新的内部 bean factory。如果存在旧的则先销毁,然后再创建新的返回。
prepareBeanFactory() 准备 bean factory
setBeanClassLoader():默认为线程上下文类加载器,用于 bean 定义加载。
setBeanExpressionResolver() spel 表达式解析设置:StandardBeanExpressionResolver。
addPropertyEditorRegistrar():ResourceEditorRegistrar 用于 bean 创建过程。
添加 ApplicationContextAwareProcessor post-processor。
注册依赖:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext。
添加 ApplicationListenerDetector post-processor:用于检测发现实现了 ApplicationListener 的 bean。
LoadTimeWeaver 处理。
environment、systemProperties、systemEnvironment、applicationStartup 注册。
postProcessBeanFactory():用于子类实现,修改内部 bean factory。
这一时期,所有的 bean 定义都已被加载,但还未实例化。
StartupStep【spring.context.beans.post-process】
invokeBeanFactoryPostProcessors() 触发所有已注册的 BeanFactoryPostProcessor
registerBeanPostProcessors() 注册 bean post-processor
StartupStep【spring.context.beans.post-process】 结束
initMessageSource() MessageSource 初始化
容器内 bean 名称:messageSource。
存在则检查并设置 ParentMessageSource。
不存在则创建默认 DelegatingMessageSource,设置 ParentMessageSource 并注册。
initApplicationEventMulticaster() 事件分发初始化
容器 bean:applicationEventMulticaster。ApplicationEventMulticaster 接口,用于管理 ApplicationListener,并执行事件分发。
不存在则创建并注册 SimpleApplicationEventMulticaster 对象。
onRefresh()
用于子类初始化一些特有的 bean。
模板方法,用于重写实现刷新逻辑。
registerListeners() 监听器注册
将实现了 ApplicationListener 接口的 bean 注册到容器。
finishBeanFactoryInitialization() 实例化所有余下的单例 bean。
conversionService。
注册内嵌值(${...})解析器。
初始化 LoadTimeWeaverAware。
停用类型匹配 ClassLoader。
freezeConfiguration() 冻结所有的 bean 定义。所有注册的 bean 定义都不允许再有变更。
preInstantiateSingletons() 实例化所有余下的单例 bean。
14、afterRefresh()ApplicationContext 刷新完毕后调用。
15、StartupInfoLogger记录应用启动信息。
16、started 事件listeners.started()
17、Runner 调用包括 ApplicationRunner 和 CommandLineRunner。
18 ready 事件listeners.ready()
上一篇: 定位中大型轿跑SUV 别克E4将于6月19日上市|天天百事通
下一篇: 最后一页
X 关闭
X 关闭
九江柴桑区:2023领春联•赏非遗之新春嘉年华
当地时间18日下午,瑞典方面发布了第一张水下照片。调查人员表示在北溪1号管道上发现了巨大且扭曲的裂缝。在此之前,只有海面上的气泡表明天然
iOS16未来新功能早在2022年的开发者大会上,苹果预览iOS16系统之时就表示了会有大量新功能加入,但直至现在的iOS16 2大版本,依然还有不少新功
今日仅6个行业获主力资金净流入,7股尾盘净流入资金超5000万元。今日沪深两市主力资金净流出93 3亿元,其中创业板净流出7 4亿元,沪深300成份
北京时间1月10日上午,“JPMorganWeek:2023中国之夜 国际生物医药创新项目路演”在美国旧金山、中国同时拉开序幕。活动中,大兴机场临空区在
与一般的侦探之间,安乐椅神探无须奔波劳碌,只需坐在舒适的安乐椅,听着、看着命案的线索,就能凭借著推理,指出真凶。角落里的
网贷逾期一般会上征信,有些借贷机构在用户逾期后一天后就会上报给征信机构,而有些借贷机构则是会在几天后上报给征信机构,因为有些借贷机构可
1月9日储能板块较上一交易日上涨0 35%,国能日新领涨。当日上证指数报收于3176 08,上涨0 58%。深证成指报收于11450 15,上涨0 72%。储能板块
网贷逾期一般会上征信,有些借贷机构在用户逾期后一天后就会上报给征信机构,而有些借贷机构则是会在几天后上报给征信机构,因为有些借贷机构可
12至15日全省有雨雪大风和强降温天气,需关注雨雪和道路结冰影响据最新气象资料监测分析,预计12至15日,受西南暖湿气流和冷空气共同影响,河