欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring的@PropertySource注解源碼解析

 更新時(shí)間:2023年11月23日 11:00:53   作者:Super_Leng  
這篇文章主要介紹了Spring的@PropertySource注解源碼解析,就以源碼時(shí)序圖的方式,直觀的感受下@PropertySource注解在Spring源碼層面的執(zhí)行流程,需要的朋友可以參考下

一、源碼時(shí)序圖

本節(jié),就以源碼時(shí)序圖的方式,直觀的感受下@PropertySource注解在Spring源碼層面的執(zhí)行流程。

@PropertySource注解在Spring源碼層面的執(zhí)行流程如圖所示:

在這里插入圖片描述

在這里插入圖片描述

由圖可以看出,@PropertySource注解在Spring源碼層面的執(zhí)行流程會(huì)涉及到PropertySourceTest類、AnnotationConfigApplicationContext類、AbstractApplicationContext類、PostProcessorRegistrationDelegate類、ConfigurationClassPostProcessor類、ConfigurationClassParser類、PropertySourceRegistry類、PropertySourceProcessor類和DefaultPropertySourceFactory類。具體的源碼執(zhí)行細(xì)節(jié)參見源碼解析部分。

二、源碼解析

@PropertySource注解在Spring源碼層面的執(zhí)行流程,結(jié)合源碼執(zhí)行的時(shí)序圖,會(huì)理解的更加深刻。

1. 運(yùn)行案例程序啟動(dòng)類

在PropertySourceTest類的main()方法中調(diào)用了AnnotationConfigApplicationContext類的構(gòu)造方法,并傳入了PropertySourceConfig類的Class對(duì)象來(lái)創(chuàng)建IOC容器。

接下來(lái),會(huì)進(jìn)入AnnotationConfigApplicationContext類的構(gòu)造方法。

注意:@PropertySource注解在Spring源碼中的執(zhí)行流程的(2)~(11)步與前面章節(jié)的@Import注解相同,這里不再贅述,直接跳到ConfigurationClassParser類的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter)方法。

2. 解析ConfigurationClassParser類的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter)方法

protected final SourceClass doProcessConfigurationClass(
    ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
    throws IOException {
    //#############省略其他代碼################
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), PropertySources.class,
        org.springframework.context.annotation.PropertySource.class)) {
        if (this.propertySourceRegistry != null) {
            this.propertySourceRegistry.processPropertySource(propertySource);
        }
    }
 //#############省略其他代碼################
}

可以看到,在ConfigurationClassParser類的doProcessConfigurationClass()方法中,遍歷獲取到的@PropertySources注解和@PropertySource注解的屬性,并且調(diào)用propertySourceRegistry對(duì)象的processPropertySource()方法解析注解屬性的值。

3. 解析PropertySourceRegistry類的processPropertySource(AnnotationAttributes propertySource)方法

void processPropertySource(AnnotationAttributes propertySource) throws IOException {
    String name = propertySource.getString("name");
    if (!StringUtils.hasLength(name)) {
        name = null;
    }
    String encoding = propertySource.getString("encoding");
    if (!StringUtils.hasLength(encoding)) {
        encoding = null;
    }
    String[] locations = propertySource.getStringArray("value");
    Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
    boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
    Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
    Class<? extends PropertySourceFactory> factorClassToUse = (factoryClass != PropertySourceFactory.class ? factoryClass : null);
    PropertySourceDescriptor descriptor = new PropertySourceDescriptor(Arrays.asList(locations), ignoreResourceNotFound, name, factorClassToUse, encoding);
    this.propertySourceProcessor.processPropertySource(descriptor);
    this.descriptors.add(descriptor);
}

可以看到,在PropertySourceRegistry類的processPropertySource()方法中,解析@PropertySource注解中的屬性后,將解析出的屬性值封裝到PropertySourceDescriptor對(duì)象中,調(diào)用propertySourceProcessor對(duì)象的processPropertySource()方法,并傳入PropertySourceDescriptor對(duì)象進(jìn)行進(jìn)一步處理。

4. 解析PropertySourceProcessor類的processPropertySource(PropertySourceDescriptor descriptor)方法

public void processPropertySource(PropertySourceDescriptor descriptor) throws IOException {
    String name = descriptor.name();
    String encoding = descriptor.encoding();
    List<String> locations = descriptor.locations();
    Assert.isTrue(locations.size() > 0, "At least one @PropertySource(value) location is required");
    boolean ignoreResourceNotFound = descriptor.ignoreResourceNotFound();
    PropertySourceFactory factory = (descriptor.propertySourceFactory() != null ? instantiateClass(descriptor.propertySourceFactory()) : DEFAULT_PROPERTY_SOURCE_FACTORY);
    for (String location : locations) {
        try {
            String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
            Resource resource = this.resourceLoader.getResource(resolvedLocation);
            addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
        }
        catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
   //#########省略其他代碼################
        }
    }
}

可以看到,在processPropertySource()方法中,會(huì)通過(guò)@PropertySource注解的屬性值解析出配置文件的內(nèi)容,并且通過(guò)factory對(duì)象的createPropertySource()方法來(lái)創(chuàng)建PropertySource對(duì)象。

5. 解析DefaultPropertySourceFactory類的createPropertySource(String name, EncodedResource resource)方法

@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
    return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource));
}

6. 回到PropertySourceProcessor類的processPropertySource(PropertySourceDescriptor descriptor)方法

在PropertySourceProcessor類的processPropertySource()方法中,創(chuàng)建完P(guān)ropertySource對(duì)象后,會(huì)調(diào)用addPropertySource()方法將獲取到的屬性值添加到Spring的環(huán)境變量中。

7. 解析PropertySourceProcessor類的addPropertySource(PropertySource<?> propertySource)方法

private void addPropertySource(org.springframework.core.env.PropertySource<?> propertySource) {
    String name = propertySource.getName();
    MutablePropertySources propertySources = this.environment.getPropertySources();
    if (this.propertySourceNames.contains(name)) {
        org.springframework.core.env.PropertySource<?> existing = propertySources.get(name);
        if (existing != null) {
            PropertySource<?> newSource = (propertySource instanceof ResourcePropertySource ?((ResourcePropertySource) propertySource).withResourceName() : propertySource);
            if (existing instanceof CompositePropertySource) {
                ((CompositePropertySource) existing).addFirstPropertySource(newSource);
            }
            else {
                if (existing instanceof ResourcePropertySource) {
                    existing = ((ResourcePropertySource) existing).withResourceName();
                }
                CompositePropertySource composite = new CompositePropertySource(name);
                composite.addPropertySource(newSource);
                composite.addPropertySource(existing);
                propertySources.replace(name, composite);
            }
            return;
        }
    }
    if (this.propertySourceNames.isEmpty()) {
        propertySources.addLast(propertySource);
    }
    else {
        String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
        propertySources.addBefore(firstProcessed, propertySource);
    }
    this.propertySourceNames.add(name);
}

可以看到,在PropertySourceProcessor類的addPropertySource()方法中,會(huì)將解析出的配置文件的內(nèi)容添加到Spring的環(huán)境變量中。

具體就是在PropertySourceProcessor類的addPropertySource()方法中,獲取到ConfigurableEnvironment中的MutablePropertySources對(duì)象,用來(lái)存儲(chǔ)解析出的配置文件中的配置項(xiàng)內(nèi)容。

如果有相同的配置項(xiàng)內(nèi)容,將existing對(duì)象強(qiáng)轉(zhuǎn)為CompositePropertySource類型,把新舊相同的配置項(xiàng)進(jìn)行合并,再放到MutablePropertySources對(duì)象中。

后續(xù)就可以通過(guò)Spring的環(huán)境變量,來(lái)獲取到配置文件中的配置項(xiàng)內(nèi)容。

至此,@PropertySource注解在Spring源碼中的執(zhí)行流程分析完畢。

到此這篇關(guān)于Spring的@PropertySource注解源碼解析的文章就介紹到這了,更多相關(guān)@PropertySource注解源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA2023創(chuàng)建MavenWeb項(xiàng)目并搭建Servlet工程的全過(guò)程

    IDEA2023創(chuàng)建MavenWeb項(xiàng)目并搭建Servlet工程的全過(guò)程

    Maven提供了大量不同類型的Archetype模板,通過(guò)它們可以幫助用戶快速的創(chuàng)建Java項(xiàng)目,這篇文章主要給大家介紹了關(guān)于IDEA2023創(chuàng)建MavenWeb項(xiàng)目并搭建Servlet工程的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • java導(dǎo)出csv格式文件的方法

    java導(dǎo)出csv格式文件的方法

    這篇文章主要為大家詳細(xì)介紹了java導(dǎo)出csv格式文件的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • Spring中統(tǒng)一異常處理示例詳解

    Spring中統(tǒng)一異常處理示例詳解

    這篇文章主要給大家介紹了關(guān)于Spring中統(tǒng)一異常處理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • SpringMVC實(shí)現(xiàn)文件下載功能

    SpringMVC實(shí)現(xiàn)文件下載功能

    這篇文章主要為大家詳細(xì)介紹了SpringMVC實(shí)現(xiàn)文件下載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • java web在高并發(fā)和分布式下實(shí)現(xiàn)訂單號(hào)生成唯一的解決方案

    java web在高并發(fā)和分布式下實(shí)現(xiàn)訂單號(hào)生成唯一的解決方案

    這篇文章主要介紹了java web在高并發(fā)和分布式下實(shí)現(xiàn)訂單號(hào)生成唯一的解決方案,需要的朋友可以參考下
    2017-11-11
  • 詳解Java分布式系統(tǒng)中session一致性問題

    詳解Java分布式系統(tǒng)中session一致性問題

    這篇文章主要介紹了Java分布式系統(tǒng)中session一致性問題,對(duì)分布式系統(tǒng)感興趣的同學(xué),要仔細(xì)看一下
    2021-04-04
  • MyBatis解決Update動(dòng)態(tài)SQL逗號(hào)的問題

    MyBatis解決Update動(dòng)態(tài)SQL逗號(hào)的問題

    這篇文章主要介紹了MyBatis解決Update動(dòng)態(tài)SQL逗號(hào)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • SpringBoot整合Web之CORS支持與配置類和 XML配置及注冊(cè)攔截器

    SpringBoot整合Web之CORS支持與配置類和 XML配置及注冊(cè)攔截器

    這篇文章主要介紹了SpringBoot整合Web開發(fā)中CORS支持與配置類和 XML配置及注冊(cè)攔截器的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • springboot中非容器類如何獲取配置文件數(shù)據(jù)

    springboot中非容器類如何獲取配置文件數(shù)據(jù)

    這篇文章主要介紹了springboot中非容器類如何獲取配置文件數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • java生成jar包的方法

    java生成jar包的方法

    這篇文章主要介紹了java生成jar包的方法,對(duì)Java生成jar包的具體步驟及方法進(jìn)行了較為詳細(xì)的描述,是非常實(shí)用的技巧,需要的朋友可以參考下
    2014-09-09

最新評(píng)論