最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot @Value實(shí)現(xiàn)獲取計(jì)算機(jī)中絕對(duì)路徑文件的內(nèi)容

 更新時(shí)間:2021年09月09日 11:24:06   作者:mysgk  
這篇文章主要介紹了springboot @Value實(shí)現(xiàn)獲取計(jì)算機(jī)中絕對(duì)路徑文件的內(nèi)容,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。

springboot @Value獲取絕對(duì)路徑文件的內(nèi)容

默認(rèn)情況下使用

@Value("aaa.txt")
private Resource txtResource;

這樣獲取到的是項(xiàng)目classpath 下的 aaa.txt

如果想獲取非項(xiàng)目路徑下的文件內(nèi)容怎么辦呢,看了下@Value的好像也沒有說,

其實(shí)

@Value("https://www.baidu.com")
private Resource urlResource;

這樣是可以獲取到 百度首頁的內(nèi)容的.它這里使用的是https協(xié)議.

同樣的我們可以使用file協(xié)議獲取文本的內(nèi)容

即:

@Value("file:///E://aaa.txt")
private Resource txtResource;

使用@Value 有一個(gè)好處就是,你不用關(guān)心文本內(nèi)容的變化,你每次調(diào)用的時(shí)候,springboot 會(huì)自動(dòng)幫你重新加載.

Spring注解@Value解讀

主要通過源碼解讀來分析@Value實(shí)現(xiàn)屬性注入Spring Bean的過程,并對(duì)static類型字段無法通過@Value注入為Spring Bean依賴的原因做一個(gè)探究。

依賴注入概述

基于Spring MVC或者Spring Boot開發(fā)后端項(xiàng)目的時(shí)候總是繞不開Spring IOC容器,Spring IOC容器管理Spring Bean,我們可以通過XML或者注解的方式來定義一個(gè)Bean,如通過注解@Service,@Controller,@Component,@Repository或者@Bean加Java配置方式。實(shí)際應(yīng)用中我們定義的一個(gè)Bean很多時(shí)候存在互相之間的依賴,比如Service層通過@Service定義的Bean往往要依賴數(shù)據(jù)庫DAO層通過@Repository定義的Bean,這時(shí)候我們往往通過@Autowired或@Resource來自動(dòng)裝配,另外還有一些Bean內(nèi)部的屬性(Field)需要通過配置文件中定義的值來設(shè)置,而后創(chuàng)建的Bean才是符合我們預(yù)期的,我們一般通過@Value和@ConfigurationProperties來實(shí)現(xiàn)屬性的注入。

實(shí)際應(yīng)用案例

以文檔管理服務(wù)為例,我們有個(gè)資源上傳的接口,其依賴一個(gè)FeignClient客戶端Bean,一個(gè)業(yè)務(wù)邏輯處理的Service Bean,還依賴一個(gè)資源上傳的OSS的桶bucket成員變量,bucket和OSS我們通常配置在配置文件中以區(qū)分不同環(huán)境。具體的依賴關(guān)系如下圖:

源碼解讀分析

首先看一下Spring Bean的的整個(gè)生命周期:

在實(shí)例化對(duì)象完成后,設(shè)置屬性值(polulateBean)之前,會(huì)搜集類上的注解元數(shù)據(jù)信息,然后在polulalteBean中攔截,執(zhí)行BeanPostProcessor中的方法,反射注入依賴的值。@Resource是jdk提供的注解,其使用的后置處理器是CommonAnnotationBeanPostProcessor,而@Autowired和@Value注解使用的后置處理器是AutowiredAnnotationBeanPostProcessor,具體的我們下面會(huì)通過代碼來解讀。

先來看一下BeanFactory和ApplicationContext在裝載bean時(shí)候的區(qū)別:

  • BeanFactory在啟動(dòng)時(shí)不會(huì)去實(shí)例化Bean,當(dāng)從容器中拿Bean的時(shí)候才會(huì)去實(shí)例化;
  • ApplicationContext在啟動(dòng)時(shí)就把所有的Bean全部實(shí)例化了??梢詾锽ean配置lazy-init=true來讓Bean延遲實(shí)例化。

我們下面以Spring Boot和ApplicationContext來走讀一下源碼:

1、首先進(jìn)入SpringApplication.run(XXXApplication.class, args)

然后一直進(jìn)入到SpringApplication的refreshContext()方法,refreshContext()是IOC容器初始化的核心方法,完成容器上下文的刷新,主要包括各種處理器、監(jiān)聽器以及Bean的初始化等工作。

2、然后進(jìn)入到AbstractApplicationContext的refresh()方法

中的finishBeanFactoryInitialization(beanFactory)方法,這個(gè)方法就是ApplicationContext完成Spring Bean實(shí)例化和初始化的關(guān)鍵方法。

3、而后進(jìn)入到DefaultListableBeanFactory的preInstantiateSingletons()方法

此方法就是獲取到所有的beanName,然后循環(huán)的去實(shí)例化+初始化bean,而實(shí)例化+初始化的方式就是調(diào)用其getBean(String name)方法,因此我們直接調(diào)到getBean(name) ,此方法的最終實(shí)現(xiàn)是在AbstractBeanFactory中,我們進(jìn)入AbstractBeanFactory的getBean(beanName)查看,然后根據(jù)調(diào)用棧直接進(jìn)入到AbstractBeanFactory的doGetBean(final String name, @Nullable final Class requiredType, @Nullable final Object[] args, boolean typeCheckOnly)方法中。這個(gè)方法代碼較多,我們直接查看我們要關(guān)注的核心代碼段如下:

4、然后我們進(jìn)入到AbstractAutowireCapableBeanFactory

createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法中,其中AbstractAutowireCapableBeanFactory是AbstractBeanFactory的一個(gè)子類,AbstractBeanFactory的createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)由AbstractAutowireCapableBeanFactory實(shí)現(xiàn)。createBean方法的核心是調(diào)用了AbstractAutowireCapableBeanFactory的doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args),我們直接查看doCreateBean方法。

5、我們略過創(chuàng)建實(shí)例的過程

直接進(jìn)入applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)方法。

5.1、applyMergedBeanDefinitionPostProcessors方法

主要是循環(huán)所有后置處理器對(duì)beanDefinition做處理,我們之前說過@Value注解是通過AutowiredAnnotationBeanPostProcessor來處理的,我們直接進(jìn)入AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)方法如下:

其中的InjectionMetadata如下,它主要封裝了bean的全限定類名和這個(gè)類中所有帶有注解的成員屬性(字段或者其他bean)描述(PropertyDescriptor,可以簡單理解為帶注解的成員屬性和注解本身兩者的組合),當(dāng)然也就包括由@Value注解的字段。

5.2、我們繼續(xù)進(jìn)入到

findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs)方法,通過buildAutowiringMetadata(final Class<?> clazz)首先獲取了當(dāng)前bean所屬類的屬性注解元數(shù)據(jù),然后存儲(chǔ)到了injectionMetadataCache緩存中,完成了applyMergedBeanDefinitionPostProcessors方法。

5.3、我們進(jìn)入到

buildAutowiringMetadata(final Class<?> clazz)查看構(gòu)建bean注入注解元數(shù)據(jù)的過程

其中用到了獲取當(dāng)前成員屬性AnnotationAttributes的方法findAutowiredAnnotation(AccessibleObject ao)如下:

其中autowiredAnnotationTypes表示后置處理器AutowiredAnnotationBeanPostProcessor處理的注解列表,初始化如下:

6、第5步完成了AbstractAutowireCapableBeanFactory

doCreateBean方法中的applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName),即完成了bean的成員屬性注解元數(shù)據(jù)的本地緩存??梢岳斫鈇pplyMergedBeanDefinitionPostProcessors為一個(gè)攔截器,即在對(duì)bean進(jìn)行成員屬性和依賴注入前先預(yù)處理bean的依賴和成員屬性數(shù)據(jù)的解析和緩存,而后再進(jìn)行populateBean。

6.1、進(jìn)入到AbstractAutowireCapableBeanFactory

populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)方法,我們直接看核心代碼如下,其中postProcessProperties方法就是完成了bean的成員屬性的初始化和依賴的注入過程。

6.2、因?yàn)槲覀円幚淼氖茾Value和@Autowired注解的bean依賴

AutowiredAnnotationBeanPostProcessor是InstantiationAwareBeanPostProcessor接口的實(shí)現(xiàn)類,所以上面代碼端循環(huán)過程中會(huì)進(jìn)入到之前的AutowiredAnnotationBeanPostProcessor的postProcessProperties(PropertyValues pvs, Object bean, String beanName)。

6.3、上面findAutowiringMetadata方法就是第5.2步的方法

也就是從緩存Map中取出bean對(duì)應(yīng)的注解元數(shù)據(jù),而后調(diào)用InjectionMetadata的inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs)方法執(zhí)行依賴注入過程。

6.4、在上面對(duì)注解元數(shù)據(jù)列表循環(huán)處理(bean依賴了多個(gè)其他的bean或者多個(gè)成員屬性通過配置注入)進(jìn)行依賴注入

調(diào)用element.inject(target, beanName, pvs)方法。而AutowiredAnnotationBeanPostProcessor類的內(nèi)部類AutowiredFieldElement繼承了InjectionMetadata.InjectedElement類,并重寫了其inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)方法,AutowiredAnnotationBeanPostProcessor類的內(nèi)部類AutowiredMethodElement也繼承了InjectionMetadata.InjectedElement類,并重寫了其inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)方法,因此6.3中的inject調(diào)用將會(huì)在此子類中執(zhí)行,AutowiredFieldElement處理成員屬性上注解,AutowiredMethodElement處理方法上注解。因此@Value注解的處理將會(huì)進(jìn)入到AutowiredFieldElement的inject方法。

6.5、首先通過beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter)方法解析依賴

然后注冊當(dāng)前bean依賴的其他bean,最后通過反射將依賴注入到當(dāng)前bean中完成bean的依賴注入過程。DefaultListableBeanFactory繼承了AbstractAutowireCapableBeanFactory類,我們先查看DefaultListableBeanFactory的resolveDependency方法,其中主要是調(diào)用了DefaultListableBeanFactory的doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter)方法,我們直接看doResolveDependency方法。

6.6、以上解析@Value注解

getSuggestedValue返回的值就是${xxx.documentcenter.bucketName:ssdocumentcenterstatic},因?yàn)槭亲址?,所以進(jìn)入到下面的邏輯AbstractBeanFactory的resolveEmbeddedValue(@Nullable String value)方法中。resolveEmbeddedValue將完成@Value注解值的解析過程,最終得到配置文件中配置的值ssdocumentcenterstatic。下面的TypeConverter的convertIfNecessary主要完成數(shù)據(jù)類型的轉(zhuǎn)換,比如配置文件中配置的Boolean類型,將String轉(zhuǎn)為Boolean等。最后返回value值并注入到bean中,此成員屬性注入到bean的過程就完成了。我們簡單看一下resolveEmbeddedValue解析過程,主要通過AbstractPropertyResolver解析器完成,其內(nèi)部使用了默認(rèn)的占位符如下:

通過其doResolvePlaceholders(String text, PropertyPlaceholderHelper helper)方法完成解析,內(nèi)部調(diào)用了PropertyPlaceholderHelper的parseStringValue(String value, PlaceholderResolver placeholderResolver, Set visitedPlaceholders)方法來具體實(shí)現(xiàn)注解的值的解析和占位替換。解析首先是從配置文件對(duì)應(yīng)的PropertySource中完成配置和值讀取,最終通過MapPropertySource實(shí)現(xiàn)。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java將XML文檔轉(zhuǎn)換成json格式數(shù)據(jù)的示例

    java將XML文檔轉(zhuǎn)換成json格式數(shù)據(jù)的示例

    本篇文章主要介紹了java將XML文檔轉(zhuǎn)換成json格式數(shù)據(jù)的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • IDEA如何開啟并配置services窗口

    IDEA如何開啟并配置services窗口

    在使用IntelliJ IDEA時(shí),可能會(huì)遇到Services窗口不自動(dòng)彈出的情況,本文介紹了如何手動(dòng)開啟Services窗口的簡單步驟,首先,通過點(diǎn)擊菜單欄中的“視圖”->“工具窗口”->“服務(wù)”,或使用快捷鍵Alt+F8(注意快捷鍵可能存在沖突)來打開Services窗口
    2024-10-10
  • Spring?boot?admin?服務(wù)監(jiān)控利器詳解

    Spring?boot?admin?服務(wù)監(jiān)控利器詳解

    這篇文章主要介紹了Spring?boot?admin?服務(wù)監(jiān)控利器詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • SpringBoot 集成Kaptcha實(shí)現(xiàn)驗(yàn)證碼功能實(shí)例詳解

    SpringBoot 集成Kaptcha實(shí)現(xiàn)驗(yàn)證碼功能實(shí)例詳解

    在一個(gè)web應(yīng)用中驗(yàn)證碼是一個(gè)常見的元素。今天給大家介紹一下kaptcha的和springboot一起使用的簡單例子。感興趣的朋友參考下吧
    2017-08-08
  • Windows下Java調(diào)用OCR進(jìn)行圖片識(shí)別

    Windows下Java調(diào)用OCR進(jìn)行圖片識(shí)別

    這篇文章主要為大家詳細(xì)介紹了Windows下Java調(diào)用OCR進(jìn)行圖片識(shí)別,通過Tesseract-OCR對(duì)圖片進(jìn)行識(shí)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Java實(shí)現(xiàn)替換PDF中的字體功能

    Java實(shí)現(xiàn)替換PDF中的字體功能

    文檔中可通過應(yīng)用不同的字體來呈現(xiàn)不一樣的視覺效果,通過字體來實(shí)現(xiàn)文檔布局、排版等設(shè)計(jì)需要。本文將詳細(xì)為大家介紹如何利用Java實(shí)現(xiàn)替換PDF文中的字體,需要的可以參考一下
    2022-03-03
  • Java中左移和右移問題圖文詳解

    Java中左移和右移問題圖文詳解

    左移和右移并不常用,在一些特殊情況下才會(huì)使用,比如加解密時(shí),會(huì)大量用到,這篇文章主要給大家介紹了關(guān)于Java中左移和右移問題的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Java中l(wèi)ombok的@Builder注解的解析與簡單使用詳解

    Java中l(wèi)ombok的@Builder注解的解析與簡單使用詳解

    這篇文章主要介紹了Java中l(wèi)ombok的@Builder注解的解析與簡單使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • 關(guān)于Java中的mysql時(shí)區(qū)問題詳解

    關(guān)于Java中的mysql時(shí)區(qū)問題詳解

    這篇文章主要給大家介紹了關(guān)于Java中mysql時(shí)區(qū)問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Java定時(shí)器Timer的源碼分析

    Java定時(shí)器Timer的源碼分析

    通過源碼分析,我們可以更深入的了解其底層原理。本文將通過Timer的源碼,帶大家深入了解Java?Timer的使用,感興趣的小伙伴可以了解一下
    2022-11-11

最新評(píng)論

高要市| 巨鹿县| 五台县| 赞皇县| 景宁| 崇仁县| 晋宁县| 雷州市| 蓝田县| 玉龙| 宽城| 五寨县| 中宁县| 合作市| 青神县| 南阳市| 建德市| 台东市| 襄城县| 大城县| 自贡市| 东乌珠穆沁旗| 邢台县| 望城县| 湄潭县| 章丘市| 新竹县| 兴山县| 政和县| 始兴县| 太保市| 芮城县| 乐平市| 中江县| 昂仁县| 获嘉县| 湖北省| 苍梧县| 雅安市| 定襄县| 锦州市|