电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

springboot中@Value的工作原理說明

瀏覽:20日期:2023-02-27 14:27:27

我們知道springboot中的Bean組件的成員變量(屬性)如果加上了@Value注解,可以從有效的配置屬性資源中找到配置項進行綁定,那么這一切是怎么發生的呢?

下文將簡要分析一下@Value的工作原理。

springboot版本: springboot-2.0.6.RELEASE

概述

springboot啟動過程中,有兩個比較重要的過程,如下:

1 掃描,解析容器中的bean注冊到beanFactory上去,就像是信息登記一樣。

2 實例化、初始化這些掃描到的bean。

@Value的解析就是在第二個階段。BeanPostProcessor定義了bean初始化前后用戶可以對bean進行操作的接口方法,它的一個重要實現類AutowiredAnnotationBeanPostProcessor正如javadoc所說的那樣,為bean中的@Autowired和@Value注解的注入功能提供支持。

解析流程調用鏈時序圖

@Value解析過程中的主要調用鏈,我用以下時序圖來表示:

springboot中@Value的工作原理說明

這里先簡單介紹一下圖上的幾個類的作用。

AbstractAutowireCapableBeanFactory: 提供了bean創建,屬性填充,自動裝配,初始胡。支持自動裝配構造函數,屬性按名稱和類型裝配。實現了AutowireCapableBeanFactory接口定義的createBean方法。

AutowiredAnnotationBeanPostProcessor: 裝配bean中使用注解標注的成員變量,setter方法, 任意的配置方法。比較典型的是@Autowired注解和@Value注解。

InjectionMetadata: 類的注入元數據,可能是類的方法或屬性等,在AutowiredAnnotationBeanPostProcessor類中被使用。

AutowiredFieldElement: 是AutowiredAnnotationBeanPostProcessor的一個私有內部類,繼承InjectionMetadata.InjectedElement,描述注解的字段。

StringValueResolver: 一個定義了處置字符串值的接口,只有一個接口方法resolveStringValue,可以用來解決占位符字符串。本文中的主要實現類在PropertySourcesPlaceholderConfigurer#processProperties方法中通過lamda表達式定義的。供ConfigurableBeanFactory類使用。

PropertySourcesPropertyResolver: 屬性資源處理器,主要功能是獲取PropertySources屬性資源中的配置鍵值對。

PropertyPlaceholderHelper: 一個工具類,用來處理帶有占位符的字符串。形如${name}的字符串在該工具類的幫助下,可以被用戶提供的值所替代。替代途經可能通過Properties實例或者PlaceholderResolver(內部定義的接口)。

PropertyPlaceholderConfigurerResolver: 上一行所說的PlaceholderResolver接口的一個實現類,是PropertyPlaceholderConfigurer類的一個私有內部類。實現方法resolvePlaceholder中調用了外部類的resolvePlaceholder方法。

調用鏈說明

這里主要介紹一下調用鏈中的比較重要的方法。

AbstractAutowireCapableBeanFactory#populateBean方法用于填充bean屬性,執行完后可獲取屬性裝配后的bean。

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { ...if (hasInstAwareBpps) {// 遍歷所有InstantiationAwareBeanPostProcessor實例設置屬性字段值。for (BeanPostProcessor bp : getBeanPostProcessors()) {// AutowiredAnnotationBeanPostProcessor會進入此分支if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);//上行代碼執行后,bw.getWrappedInstance()就得到了@Value注解裝配屬性后的bean了if (pvs == null) {return;}}}}...}

InjectionMetadata#inject逐個裝配bean的配置屬性。

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {Collection<InjectedElement> checkedElements = this.checkedElements;Collection<InjectedElement> elementsToIterate =(checkedElements != null ? checkedElements : this.injectedElements);if (!elementsToIterate.isEmpty()) { // 依次注入屬性for (InjectedElement element : elementsToIterate) {if (logger.isDebugEnabled()) {logger.debug('Processing injected element of bean ’' + beanName + '’: ' + element);}element.inject(target, beanName, pvs);}}}

PropertyPlaceholderHelper#parseStringValue解析屬性值

/** * 一個參數示例 value = '${company.ceo}' * */protected String parseStringValue(String value, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {StringBuilder result = new StringBuilder(value);// this.placeholderPrefix = '${'int startIndex = value.indexOf(this.placeholderPrefix);while (startIndex != -1) {// 占位符的結束位置,以value = '${company.ceo}'為例,endIndex=13int endIndex = findPlaceholderEndIndex(result, startIndex);if (endIndex != -1) {// 獲取{}里的真正屬性名稱,此例為'company.ceo'String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);String originalPlaceholder = placeholder;if (!visitedPlaceholders.add(originalPlaceholder)) {throw new IllegalArgumentException('Circular placeholder reference ’' + originalPlaceholder + '’ in property definitions');}// Recursive invocation, parsing placeholders contained in the placeholder key.// 遞歸調用本方法,因為屬性鍵中可能仍然有占位符placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);// Now obtain the value for the fully resolved key...// 獲取屬性鍵placeholder對應的屬性值String propVal = placeholderResolver.resolvePlaceholder(placeholder);// 此處邏輯是當company.ceo=${bi:li}時,company.ceo最終被li所替代的原因// 所以配置文件中,最好不要出現類似${}的東西,因為它本身就會被spring框架所解析if (propVal == null && this.valueSeparator != null) {int separatorIndex = placeholder.indexOf(this.valueSeparator);if (separatorIndex != -1) {String actualPlaceholder = placeholder.substring(0, separatorIndex);String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);if (propVal == null) {propVal = defaultValue;}}}if (propVal != null) {// Recursive invocation, parsing placeholders contained in the// previously resolved placeholder value.propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);// 將${company.ceo}替換為liresult.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);if (logger.isTraceEnabled()) {logger.trace('Resolved placeholder ’' + placeholder + '’');}startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());}else if (this.ignoreUnresolvablePlaceholders) {// Proceed with unprocessed value.startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());}else {throw new IllegalArgumentException('Could not resolve placeholder ’' +placeholder + '’' + ' in value '' + value + ''');}visitedPlaceholders.remove(originalPlaceholder);}else {startIndex = -1;}}return result.toString();}總結

@Value注解標注的bean屬性裝配是依靠AutowiredAnnotationBeanPostProcessor在bean的實例化、初始化階段完成的。以上為個人經驗,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Spring
相關文章:
主站蜘蛛池模板: 物和码官网,物和码,免费一物一码数字化营销SaaS平台 | 咖啡加盟,咖啡店加盟连锁品牌-卡小逗 | 南昌旅行社_南昌国际旅行社_南昌国旅在线 | 优考试_免费在线考试系统_培训考试系统_题库系统_组卷答题系统_匡优考试 | 三佳互联一站式网站建设服务|网站开发|网站设计|网站搭建服务商 赛默飞Thermo veritiproPCR仪|ProFlex3 x 32PCR系统|Countess3细胞计数仪|371|3111二氧化碳培养箱|Mirco17R|Mirco21R离心机|仟诺生物 | 螺杆真空泵_耐腐蚀螺杆真空泵_水环真空泵_真空机组_烟台真空泵-烟台斯凯威真空 | 大行程影像测量仪-探针型影像测量仪-增强型影像测量仪|首丰百科 大通天成企业资质代办_承装修试电力设施许可证_增值电信业务经营许可证_无人机运营合格证_广播电视节目制作许可证 | 智慧旅游_智慧景区_微景通-智慧旅游景区解决方案提供商 | 海外整合营销-独立站营销-社交媒体运营_广州甲壳虫跨境网络服务 焊管生产线_焊管机组_轧辊模具_焊管设备_焊管设备厂家_石家庄翔昱机械 | 冷藏车厂家|冷藏车价格|小型冷藏车|散装饲料车厂家|程力专用汽车股份有限公司销售十二分公司 | 西装定制/做厂家/公司_西装订做/制价格/费用-北京圣达信西装 | CCE素质教育博览会 | CCE素博会 | 教育展 | 美育展 | 科教展 | 素质教育展 | 自动配料系统_称重配料控制系统厂家| 长沙发电机-湖南发电机-柴油发电机供应厂家-长沙明邦智能科技 | 高通量组织研磨仪-多样品组织研磨仪-全自动组织研磨仪-研磨者科技(广州)有限公司 | 语料库-提供经典范文,文案句子,常用文书,您的写作得力助手 | ET3000双钳形接地电阻测试仪_ZSR10A直流_SXJS-IV智能_SX-9000全自动油介质损耗测试仪-上海康登 | hc22_hc22价格_hc22哈氏合金—东锜特殊钢 | 武汉宣传片制作-视频拍摄-企业宣传片公司-武汉红年影视 | 上海律师事务所_上海刑事律师免费咨询平台-煊宏律师事务所 | 肉嫩度仪-凝胶测试仪-国产质构仪-气味分析仪-上海保圣实业发展有限公司|总部 | 亳州网络公司 - 亳州网站制作 - 亳州网站建设 - 亳州易天科技 | 橡胶弹簧|复合弹簧|橡胶球|振动筛配件-新乡市永鑫橡胶厂 | 济南ISO9000认证咨询代理公司,ISO9001认证,CMA实验室认证,ISO/TS16949认证,服务体系认证,资产管理体系认证,SC食品生产许可证- 济南创远企业管理咨询有限公司 郑州电线电缆厂家-防火|低压|低烟无卤电缆-河南明星电缆 | 垃圾处理设备_餐厨垃圾处理设备_厨余垃圾处理设备_果蔬垃圾处理设备-深圳市三盛环保科技有限公司 | 空气能采暖,热泵烘干机,空气源热水机组|设备|厂家,东莞高温热泵_正旭新能源 | 游动电流仪-流通式浊度分析仪-杰普仪器(上海)有限公司 | 厦门ISO认证|厦门ISO9001认证|厦门ISO14001认证|厦门ISO45001认证-艾索咨询专注ISO认证行业 | 直流电能表-充电桩电能表-导轨式电能表-智能电能表-浙江科为电气有限公司 | 柔软云母板-硬质-水位计云母片组件-首页-武汉长丰云母绝缘材料有限公司 | 北京森语科技有限公司-模型制作专家-展览展示-沙盘模型设计制作-多媒体模型软硬件开发-三维地理信息交互沙盘 | 深圳富泰鑫五金_五金冲压件加工_五金配件加工_精密零件加工厂 | 石磨面粉机|石磨面粉机械|石磨面粉机组|石磨面粉成套设备-河南成立粮油机械有限公司 | 免费个人pos机申请办理-移动pos机刷卡-聚合收款码办理 | 酒糟烘干机-豆渣烘干机-薯渣烘干机-糟渣烘干设备厂家-焦作市真节能环保设备科技有限公司 | 鹤壁创新仪器公司-全自动量热仪,定硫仪,煤炭测硫仪,灰熔点测定仪,快速自动测氢仪,工业分析仪,煤质化验仪器 | 双杰天平-国产双杰电子天平-美国双杰-常熟双杰仪器 | 云南外加剂,云南速凝剂,云南外加剂代加工-普洱澜湄新材料科技有限公司 | 全自动在线分板机_铣刀式在线分板机_曲线分板机_PCB分板机-东莞市亿协自动化设备有限公司 | 热处理温控箱,热处理控制箱厂家-吴江市兴达电热设备厂 | 上海皓越真空设备有限公司官网-真空炉-真空热压烧结炉-sps放电等离子烧结炉 |