您现在的位置: 首页 论文选粹 > > 正文
微速讯:spring启动流程 (1) 流程概览
发布时间:2023-06-27 04:07:39 来源:博客园

本文将通过阅读AnnotationConfigApplicationContext源码,分析Spring启动流程。


(资料图片仅供参考)

创建AnnotationConfigApplicationContext

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();applicationContext.register(XxConfig.class);applicationContext.register(YyConfig.class);applicationContext.refresh();XxService xxService = applicationContext.getBean(XxService.class);

核心的启动逻辑都在refresh方法中。

构造方法

public AnnotationConfigApplicationContext() {this.reader = new AnnotatedBeanDefinitionReader(this);this.scanner = new ClassPathBeanDefinitionScanner(this);}

AnnotatedBeanDefinitionReader类

定义了多个register方法,用于向Spring容器注册BeanDefinition。

在创建AnnotatedBeanDefinitionReader时,会向容器注册几个注解驱动处理器:

  • org.springframework.context.annotation.internalConfigurationAnnotationProcessor: ConfigurationClassPostProcessor
    • BeanFactoryPostProcessor实现,用于解析@Configuration类。
    • 按优先级排序,因为在@Configuration类中声明的任何@Bean方法都必须在任何其他BeanFactoryPostProcessor执行之前注册其对应的BeanDefinition。
  • org.springframework.context.annotation.internalAutowiredAnnotationProcessor: AutowiredAnnotationBeanPostProcessor
    • BeanPostProcessor实现类。
    • @Autowired支持处理器。
  • org.springframework.context.annotation.internalCommonAnnotationProcessor: CommonAnnotationBeanPostProcessor
    • BeanPostProcessor实现类。
    • 支持Resource、PostConstruct、PreDestroy等注解。
  • org.springframework.context.event.internalEventListenerProcessor: EventListenerMethodProcessor
  • org.springframework.context.event.internalEventListenerFactory: DefaultEventListenerFactory

ClassPathBeanDefinitionScanner类

BeanDefinition扫描器,在类路径上检测Bean,并将其注册到Spring容器中。扫描的类是通过类型过滤器检测到的。

refresh方法

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 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);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// 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) {// 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();}}}

prepareRefresh方法

Prepare this context for refreshing, setting its startup date and active flag as well as performing any initialization of property sources.

protected void prepareRefresh() {// Switch to active.this.startupDate = System.currentTimeMillis();this.closed.set(false);this.active.set(true);// Initialize any placeholder property sources in the context environment.// Replace any stub property sources with actual instances.// web相关的ApplicationContext有实现initPropertySources();// Validate that all properties marked as required are resolvable:// see ConfigurablePropertyResolver#setRequiredPropertiesgetEnvironment().validateRequiredProperties();// Store pre-refresh ApplicationListeners...if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);} else {// Reset local application listeners to pre-refresh state.this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}// Allow for the collection of early ApplicationEvents,// to be published once the multicaster is available...this.earlyApplicationEvents = new LinkedHashSet<>();}

obtainFreshBeanFactory方法

Tell the subclass to refresh the internal bean factory.

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();return getBeanFactory();}

由于AnnotationConfigApplicationContext继承了GenericApplicationContext类,所以此处获取到的是DefaultListableBeanFactory对象。

prepareBeanFactory方法

配置BeanFactory的标准上下文,例如上下文的ClassLoader和后置处理器。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the context"s class loader etc.beanFactory.setBeanClassLoader(getClassLoader());// Standard implementation of the BeanExpressionResolver interface,// parsing and evaluating Spring EL using Spring"s expression module.beanFactory.setBeanExpressionResolver(        new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// Configure the bean factory with context callbacks.// 支持EnvironmentAware, MessageSourceAware, ApplicationContextAware等beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));beanFactory.ignoreDependencyInterface(EnvironmentAware.class);beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);// BeanFactory interface not registered as resolvable type in a plain factory.// MessageSource registered (and found for autowiring) as a bean.beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// ApplicationListenerDetector处理器自动将ApplicationListener类型Bean添加容器beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// 注册env beanif (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory            .registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}}

postProcessBeanFactory方法

Modify the application context"s internal bean factory after its standard initialization. All bean definitions will have been loaded, but no beans will have been instantiated yet. This allows for registering special BeanPostProcessors etc in certain ApplicationContext implementations.

在标准初始化之后修改ApplicationContext的内部bean工厂。所有的BeanDefinition都将被加载,但还没有任何Bean被实例化。这允许在某些ApplicationContext实现中注册特殊的BeanPostProcessors等。

invokeBeanFactoryPostProcessors方法

实例化并调用注册的所有BeanFactoryPostProcessor,如果指定顺序则按照顺序调用,必须在单例实例化之前调用。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 调用BeanFactoryPostProcessorsPostProcessorRegistrationDelegate        .invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}}

调用BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。

registerBeanPostProcessors方法

实例化并注册所有BeanPostProcessor,如果指定顺序则按照顺序注册,必须在应用Bean实例化之前调用。

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);}

把BeanPostProcessor实例添加到beanPostProcessors中:

  1. 从容器获取所有的BeanPostProcessor Bean
  2. 按照以下顺序注册:实现了PriorityOrdered接口、实现了Ordered接口、普通BeanPostProcessor、实现MergedBeanDefinitionPostProcessor接口
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List postProcessors) {for (BeanPostProcessor postProcessor : postProcessors) {beanFactory.addBeanPostProcessor(postProcessor);}}

initMessageSource方法

国际化。

protected void initMessageSource() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);// Make MessageSource aware of parent MessageSource.if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;if (hms.getParentMessageSource() == null) {// Only set parent context as parent MessageSource if no parent MessageSource// registered already.hms.setParentMessageSource(getInternalParentMessageSource());}}} else {// Use empty MessageSource to be able to accept getMessage calls.DelegatingMessageSource dms = new DelegatingMessageSource();dms.setParentMessageSource(getInternalParentMessageSource());this.messageSource = dms;beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);}}

initApplicationEventMulticaster方法

初始化ApplicationEventMultimaster,如果Context中未定义,则使用SimpleApplicationEventMultimaster。

protected void initApplicationEventMulticaster() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {this.applicationEventMulticaster = beanFactory.getBean(            APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);} else {this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);beanFactory.registerSingleton(            APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);}}

onRefresh方法

可以重写的模板方法,以添加指定的刷新逻辑。在初始化特殊Bean时调用,在实例化单例之前调用。

默认什么都不做。

SpringBoot中的ServletWebServerApplicationContext实现类在这个阶段创建WebServer。

registerListeners方法

添加实现ApplicationListener的Bean作为侦听器。不会影响其他侦听器,这些侦听器可以在不使用Bean的情况下添加。

finishBeanFactoryInitialization方法

完成Bean工厂的初始化,初始化所有剩余的单例Bean。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.beanFactory.preInstantiateSingletons();}

finishRefresh方法

完成刷新工作,调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent事件。

protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning).clearResourceCaches();// Initialize lifecycle processor for this context.initLifecycleProcessor();// Propagate refresh to lifecycle processor first.getLifecycleProcessor().onRefresh();// Publish the final event.publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.LiveBeansView.registerApplicationContext(this);}

启动流程

  1. 创建AnnotationConfigApplicationContext对象
    • 创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
    • 向容器注册几个注解驱动处理器:ConfigurationClassPostProcessor, AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor等
  2. 调用applicationContext.register(XxConfig.class)注册配置类
  3. 调用refresh()方法:
    • prepareRefresh方法准备工作:初始化PropertySources、validateRequiredProperties等
    • Refresh the internal beanFactory
    • 配置BeanFactory的标准上下文,例如上下文的ClassLoader和后置处理器
    • 实例化并调用注册的所有BeanFactoryPostProcessor,如果指定顺序则按照顺序调用,必须在单例实例化之前调用
    • 实例化并注册所有BeanPostProcessor,如果指定顺序则按照顺序注册,必须在应用Bean实例化之前调用
    • 初始化MessageSource
    • 初始化ApplicationEventMultimaster,如果Context中未定义,则使用SimpleApplicationEventMultimaster
    • onRefresh方法,SpringBoot中的ServletWebServerApplicationContext实现类在这个阶段创建WebServer
    • 添加实现ApplicationListener的Bean作为侦听器
    • 完成Bean工厂的初始化,初始化所有剩余的单例Bean
    • 完成刷新工作,调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent事件

标签:

微速讯:spring启动流程 (1) 流程概览

本文将通过阅读AnnotationConfigApplicationContext源码,分析Spring启

视讯!回收站删除的图片还能恢复吗

回收站删除的图片可以恢复吗如何正确使用?这是很多用户都在问的,这款

中国银行女儿金金条价格今天多少一克(2023年06月26日)

金投网提供中国银行女儿金金条价格今天多少一克(2023年06月26日),中

阳光城为四家子公司提供合计9.675亿元连带责任担保

截至公告披露日,阳光城及控股子公司对参股公司提供担保实际发生金额为

鸡丝肉的做法鸡胸肉?

用料鸡胸肉1块黄瓜半根芹菜2根香菜2根葱2根蒜4瓣辣椒2个盐焗粉5克(四

小熊电器:第三大股东龙少柔拟减持不超100万股公司股份_当前头条

小熊电器6月26日公告,持有公司1192 3511万煤股(占公司总股本比例7 62

广东普通类考生超33万人上本科线 比去年减少了1241人

南都讯记者孙小鹏6月26日,南都记者从广东省教育考试院获悉,广东省202

全球实时:辽宁男篮第4人!篮协宣布任命,夺冠功勋驰援男篮集训

辽宁男篮第4人!篮协宣布任命,夺冠功勋驰援男篮集训,杨鸣,辽篮,篮协,

全球热讯:上海市地方金融监管局局长周小全会见复星国际董事长郭广昌一行

上海市地方金融监管局官微消息,2023年6月25日,上海市地方金融监管局

时讯:复苏挑战下 小微经营者生存境况如何?

小微企业数量占中国市场主体的90%,是消费复苏的温度计与晴雨表,也是

英雄联盟手游默契之心怎么激活 默契之心激活方法介绍|全球短讯

英雄联盟是一款非常火爆的moba类团队竞技游戏,由同名端游移植为手机

顺丰特惠快递单号查询系统_顺丰特惠快递单号查询|前沿热点

1、顺丰速运已收取快件2018-04-2917:29:06快件在【常州钟楼新闸营业点

王楠 甲状腺癌 王楠甲状腺癌医院)

王楠甲状腺癌王楠甲状腺癌甲状腺癌是一种相对不太常见的癌症,但是对于

全球观热点:中国人民大学报告:预计上半年中国经济增长6.2% 基础坚实

中国宏观经济分析与预测报告于6月25日在中国人民大学宏观经济论坛上发

今日快讯:聊天回“OK”成被告,表情包要有“法治脸”

据极目新闻报道,近日,江西法院微信公众号一篇《回了个“OK”,江西一

世界热文:闻过则喜知过不悔_ldquo 闻过则喜 知过不讳 改过不惮 rdquo 字词句的意思是什么

1、听到别人说自己有错应当高兴,知道自己的过失应当不隐讳,而改正自

【原耽双男主小说推荐】[完结] 错误投送 作者:麦起txt 全球即时看

链接:https: pan xunlei com s VNYrZI3rwiWL1_jpEvjM6gNcA1?pwd=upjx

环球快看点丨魔法异闻录手游官网在哪下载 最新官方下载安装地址

魔法异闻录手游怎么下载?想要比别人更加抢先抢快的玩到这款游戏,那么

北京抓获143名“黄牛”!将研究实名入场、取消转赠、退换票等政策

北京多部门于4月起联合发起了为期5个月的打击演出票务市场“黄牛”非法

欧陆战争4无限勋章金币版下载_欧陆战争4

1、没有无限行动力的,你可以用apk脚本编辑器和re文件管理器制作MOD,

毕业典礼泪点直拍!祝福毕业生,前程似锦_今日热文

毕业季进入尾声。对很多人来说,毕业典礼,就是大学的最后一份仪式

填补国内空白!我国首艘深远海多功能科考船开工建造

25日,我国首艘深远海多功能科学考察及文物考古船在广州开工建造。该船

工行的融e借好通过吗?审核失败原因为你解答!

工行的融e借好通过吗?审核失败原因为你解答!融e借是工商银行向符合条

环球速看:苹果怎么削皮不断的小技巧

关于苹果怎么削皮不断的小技巧的内容,包含苹果怎么削皮不断呢苹果怎么

14300+600个!北京小客车今日摇号,中签率或有变化

据北京市小客车指标调控管理办公室消息,26日上午10时,北京市开展2023

界牌镇多举措持续优化营商环境

环球观热点:“只要孩子安全,比什么都强!”|全球热讯

中国跨境电商逐鹿世界舞台

台媒直呼惊险!大陆8架军机抵近台湾,台军竖导弹欲打“第一枪”

四天两艘!外高桥边检站连续助力新一代中型集装箱船首航

品质差的人,不安于富贵,也不安于贫贱

坚持以客户伙伴为中心 广汽汇理智慧金融服务满足多元化需求_环球热闻

人民财评:文旅市场复苏势头强劲 继续释放消费潜力 每日速看

牛奶好还是羊奶好有什么区别_牛奶好还是羊奶好 环球关注

水豆豉的做法?

一图看懂vivo X90s 配置全面升级3999起

电力设备及新能源行业周报:异质结组件订单频签订,海外风机巨头产品质量隐患显现_世界关注

比尔盖茨看多 科威特政府基金加仓 这只化工巨头获机构最多关注 环球快看点

“中国球员要让自己的努力配得上中国的伟大”-天天简讯

衡阳市建筑施工“安全生产月”系列活动暨相关培训在衡阳高新区举行|世界快资讯

观察:伊布ins晒与奇马耶夫合影:狼不会在马戏团表演

2021南阳师范学院学科教师公费师范生录取分数线

2023年中国内地电影总票房破250亿元-快资讯

6月26日山东舜天液氨报价持稳 全球热消息

8岁男孩在武术俱乐部被打致死?警方:三人被采取刑事强制措施

疑似荣耀Magic V2双版本入网 分别搭载骁龙8+和骁龙8 Gen 2 百事通

有机肥让土壤更健康

造车,还是得学苹果? 关注

环球观焦点:梁文博长文回应!承认参与赌球,称被人泼脏水,球迷:这是在狡辩

海贼王:假如路飞第一话就觉醒了尼卡形态,艾斯就不会死_快看

气象专家:厄尔尼诺将给我国带来哪些影响?

2023年上海社保卡个人账号密码如何申请 天天实时

福特翼虎2013四驱系统_福特翼虎2013

信用卡逾期三年了银行会怎样处理?用卡挂账停息需要什么条件? 天天观天下|今日热搜

三星Galaxy S24系列内部代号曝光:来源于缪斯女神 看点

3927万,再见76人!无奈遭四处兜售,费城屡次失败问题并不在你

中国交通运输部:端午假期预计发送旅客超1.4亿人次

对于我国偷越国境罪的量刑标准有什么 天天短讯

中国—中南半岛跨境物流重点口岸城市合作论坛在凭祥市举办-环球视讯

全球讯息:“启迪并挖掘每个学生的闪光点!”

【全球速看料】疯狂萨满热带冒险

皮肤暗黄是怎么回事? 世界速读

时讯:二十年,焕然一新

上市公司发喜报称总经理女儿勇夺“高考状元” 网友:这算违反禁令吗

福特拒绝特斯拉Cybertruck:不为实做事,只为硅谷人设计 全球新资讯

梅雨“二访”带来“暴雨江南” 多地气温跌至“2”字头

放松一“夏”,未来皆可期!@中、高考同学,这份贵州毕业旅行攻略请查收!

环球快看点丨2023年9月贵州计算机等级考试报名时间及报名网址入口

下赛季提前报销!再见了,NBA!他真的很难再回来!_观速讯

买房贷款多久能批下来,买房贷款流程介绍?_环球微速讯

微宏流程机器人,让应用集成变得轻松

一次活动“带火”一座城 2023河南省文旅文创发展大会缘何花开洛阳

“千名硕博进高新”,济南高新区释放了怎样的信号-全球快看点

斋月吉庆祝福语(斋月吉庆祝福语图片)|今日精选

春秋航空:抛售南航!_每日快讯

x 广告
x 广告

Copyright ©  2015-2022 亚洲自然网版权所有  备案号:京ICP备2021034106号-51   联系邮箱:5 516 538 @qq.com