Spring 应用的启动类。
【资料图】
创建 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日,受西南暖湿气流和冷空气共同影响,河