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

Spring中@PropertySource的使用方法和運(yùn)行原理詳解

 更新時(shí)間:2023年11月23日 09:31:10   作者:dream21st  
這篇文章主要介紹了Spring中@PropertySource的使用方法和運(yùn)行原理詳解,PropertySource注解可以方便和靈活的向Spring的環(huán)境容器(org.springframework.core.env.Environment?Environment)中注入一些屬性,這些屬性可以在Bean中使用,需要的朋友可以參考下

1 @PropertySource使用方法和運(yùn)行原理機(jī)制詳解

1.1 @PropertySource簡(jiǎn)要說明

PropertySource注解可以方便和靈活的向Spring的環(huán)境容器(org.springframework.core.env.Environment Environment)中注入一些屬性,這些屬性可以在Bean中使用。

1.2 @PropertySource基本使用

首先,我們用idea構(gòu)建一個(gè)Springboot項(xiàng)目,項(xiàng)目的pom.xml具體內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.11.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>springboot-code</artifactId>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

項(xiàng)目構(gòu)建完畢后,我們打開@PropertySource類,可以看到其基本內(nèi)容如下:

package org.springframework.context.annotation;
 
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.io.support.PropertySourceFactory;
 
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
/**
* @PropertySource可以在PropertySources中復(fù)用
**/
@Repeatable(PropertySources.class)
public @interface PropertySource {
 
	/**
	* 該P(yáng)ropertySource的名字,如果不指定會(huì)用文件名按照一定的方式生成
	**/
	String name() default "";
 
	/**
	* 指定掃描文件的路徑,可以配置多個(gè)
	**/
	String[] value();
 
	/**
	* 是否忽略文件,如果文件沒有找到,默認(rèn)否,就是如果沒有文件會(huì)報(bào)錯(cuò)
	**/
	boolean ignoreResourceNotFound() default false;
 
	/**
	* 指定文件編碼
	**/
	String encoding() default "";
 
	/**
	* 指定文件解析工廠
	**/
	Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
 
}

1.2.1 讀取.properties結(jié)尾的配置文件

首先在resources資源目錄下面建一個(gè)文件名為women.properties的文件,文件的具體內(nèi)容如下:

women.name=lili
women.age=18

接著我們編寫一個(gè)Women的類,并在上面通過@PropertySource的方式加載women.properties文件,同時(shí)通過@Value注入的方式把配置文件中的值注入到Women類的相關(guān)屬性上面,最終在Women類上加上@Component注解交給容器管理。相關(guān)代碼的內(nèi)容如下:

package com.dream21th.service;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
 
@Component
@PropertySource(value = "classpath:women.properties")
public class Women {
 
    @Value("${women.name}")
    private String name;
 
    @Value("${women.age}")
    private String age;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getAge() {
        return age;
    }
 
    public void setAge(String age) {
        this.age = age;
    }
 
    @Override
    public String toString() {
        return "Women{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }
}

1.2.2 讀取.xml結(jié)尾的配置文件

首先在resources資源目錄下面建一個(gè)文件名為men.properties的文件,文件的具體內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <entry key="man.name">李白</entry>
    <entry key="man.hobby">寫詩</entry>
</properties>

接著我們編寫一個(gè)Men的類,并在上面通過@PropertySource的方式加載men.xml文件,同時(shí)通過@Value注入的方式把配置文件中的值注入到Men類的相關(guān)屬性上面,最終在Men類上加上@Component注解交給容器管理。相關(guān)代碼的內(nèi)容如下:

package com.dream21th.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
 
@Component
@PropertySource(value = "classpath:men.xml")
public class Men {
 
    @Value("${man.name}")
    private String name;
 
    @Value("${man.hobby}")
    private String hobby;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getHobby() {
        return hobby;
    }
 
    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
 
    @Override
    public String toString() {
        return "Men{" +
                "name='" + name + '\'' +
                ", hobby='" + hobby + '\'' +
                '}';
    }
}

1.2.3 讀取.yml或者.yaml結(jié)尾的配置文件

由于默認(rèn)的DefaultPropertySourceFactory資源工廠并不能解析.yml或者.yaml結(jié)尾的配置文件。在此,我們先要自定義一個(gè)YAML解析的資源工廠,具體代碼實(shí)現(xiàn)如下:

package com.dream21th.config;
 
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import java.io.IOException;
import java.util.Properties;
 
public class YAMLPropertySourceFactory implements PropertySourceFactory {
 
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) throws IOException {
        //1,創(chuàng)建一個(gè)YAML文件的解析工廠。
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        //2,設(shè)置資源。
        factory.setResources(encodedResource.getResource());
 
        //3,獲取解析后的Properties對(duì)象
        Properties properties = factory.getObject();
        //4返回。此時(shí)不能像默認(rèn)工廠那樣返回ResourcePropertySource對(duì)象 ,要返回他的父類PropertiesPropertySource對(duì)象。
        return name != null ? new PropertiesPropertySource(name, properties) :
                new PropertiesPropertySource(encodedResource.getResource().getFilename(),properties);
    }
}

接著在resources資源目錄下面建一個(gè)文件名為person.yml的文件,文件的具體內(nèi)容如下:

person:
  name: zhangsan
  address: shanghaihsi

接著我們編寫一個(gè)Person的類,并在上面通過@PropertySource的方式加載person.yml文件,在配置文件的同時(shí)要指定資源文件的解析工廠類,這里我們指定為YAMLPropertySourceFactory.class。同時(shí)通過@Value注入的方式把配置文件中的值注入到Person類的相關(guān)屬性上面,最終在Person類上加上@Component注解交給容器管理。相關(guān)代碼的內(nèi)容如下:

package com.dream21th.service;
 
import com.dream21th.config.YAMLPropertySourceFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
 
@Component
@PropertySource(value = "classpath:person.yml",factory = YAMLPropertySourceFactory.class)
public class Person {
 
    @Value("${person.name}")
    private String name;
 
    @Value("${person.address}")
    private String address;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getAddress() {
        return address;
    }
 
    public void setAddress(String address) {
        this.address = address;
    }
 
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", address='" + address +
                '}';
    }
}

1.2.4 讀取其他方式結(jié)尾的配置文件

嚴(yán)格意義上面來講,默認(rèn)的DefaultPropertySourceFactory屬性讀取工廠,不僅僅只能讀取.properties和xml結(jié)尾的配置文件?;疽饬x上能讀取所有后綴的文件,只要文件里面的內(nèi)容按照.properties的方式拼寫。

我們?cè)趓esources資源目錄下面建一個(gè)文件名為other.xxx(xxx代表任意文件的后綴)的文件,文件的具體內(nèi)容如下:

other.name=異類
other.home=火星

接著我們編寫一個(gè)Other的類,并在上面通過@PropertySource的方式加載other.xxx文件,在配置文件的同時(shí)要指定資源文件的編碼,這里我們指定為utf-8。同時(shí)通過@Value注入的方式把配置文件中的值注入到Person類的相關(guān)屬性上面,最終在Other類上加上@Component注解交給容器管理。相關(guān)代碼的內(nèi)容如下:

package com.dream21th.service;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
 
@Component
@PropertySource(value = "classpath:other.xxx",encoding = "utf-8")
public class Other {
 
    @Value("${other.name}")
    private String name;
 
    @Value("${other.home}")
    private String home;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getHome() {
        return home;
    }
 
    public void setHome(String home) {
        this.home = home;
    }
 
    @Override
    public String toString() {
        return "Other{" +
                "name='" + name + '\'' +
                ", home='" + home + '\'' +
                '}';
    }
}

1.2.5 測(cè)試

在啟動(dòng)類下面注入上面例子中的Bean,在容器啟動(dòng)成功后打印相關(guān)數(shù)據(jù),具體實(shí)現(xiàn)代碼如下:

package com.dream21th;
 
import com.dream21th.service.Men;
import com.dream21th.service.Other;
import com.dream21th.service.Person;
import com.dream21th.service.Women;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class SpringbootSourceApplication implements CommandLineRunner {
 
    @Autowired
    private Person person;
 
    @Autowired
    private Women women;
 
    @Autowired
    private Men men;
 
    @Autowired
    private Other other;
 
    public static void main(String[] args) {
        SpringApplication.run(SpringbootSourceApplication.class,args);
    }
 
    @Override
    public void run(String... args) throws Exception {
        System.out.println(person);
 
        System.out.println(women);
 
        System.out.println(men);
 
        System.out.println(other);
    }
}

啟動(dòng)成功后,控制臺(tái)的輸出內(nèi)容如下,代表我們通過四種文件類型的屬性讀取成功。

Person{name='zhangsan', address='shanghaihsi}
Women{name='lili', age='18'}
Men{name='李白', hobby='寫詩'}
Other{name='異類', home='火星'}

1.3 @PropertySource使用小結(jié)

通過上面的例子,我們可以讀取不同后綴的文件中的內(nèi)容到容器中去。同時(shí)也要說明,雖然上面我們是一個(gè)配置文件一個(gè)類,并且也是在對(duì)應(yīng)類里面使用對(duì)應(yīng)屬性。但并不代表只能這樣用,@PropertySource屬性中的value屬性是可以輸入多個(gè)路徑的,我們可以在一個(gè)文件中加載所有的文件,然后再其他的實(shí)例中使用相關(guān)的屬性。當(dāng)然也可以在@PropertySources中使用多個(gè)@PropertySource的方式來讀取文件。

1.4 @PropertySource運(yùn)行原理機(jī)制

源碼的啟動(dòng)過程比較復(fù)雜和繁瑣,由于篇幅有限,在這里,我們就不追代碼,直接定位到對(duì)應(yīng)的處理邏輯代碼上。

我們定位到org.springframework.context.annotation.ConfigurationClassParser類的doProcessConfigurationClass方法上面來。

@Nullable
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {
 
		//此處省略一些代碼
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                /**
                * 類上面有PropertySources.class
                **/
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
                //處理邏輯
				processPropertySource(propertySource);
			}
			else {
				logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}
        //此處省略一些代碼
        
    }
private 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");
        //文件解析工廠
		PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
				DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
 
		for (String location : locations) {
			try {
				String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
				Resource resource = this.resourceLoader.getResource(resolvedLocation);
                //實(shí)際處理邏輯
				addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
			}
			catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
				// Placeholders not resolvable or resource not found when trying to open it
				if (ignoreResourceNotFound) {
					if (logger.isInfoEnabled()) {
						logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
					}
				}
				else {
					throw ex;
				}
			}
		}
	}
//加到Environment中
private void addPropertySource(PropertySource<?> propertySource) {
		String name = propertySource.getName();
		MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();
 
		if (this.propertySourceNames.contains(name)) {
			// We've already added a version, we need to extend it
			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);
	}

到此這篇關(guān)于Spring中@PropertySource的使用方法和運(yùn)行原理詳解的文章就介紹到這了,更多相關(guān)@PropertySource的使用方法和運(yùn)行原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Micronaut框架的簡(jiǎn)單使用介紹

    Micronaut框架的簡(jiǎn)單使用介紹

    這篇文章主要介紹了Micronaut框架的簡(jiǎn)單使用介紹,幫助大家更好的理解和學(xué)習(xí)使用Micronaut,感興趣的朋友可以了解下
    2021-04-04
  • springboot自動(dòng)裝配之@ComponentScan使用方式

    springboot自動(dòng)裝配之@ComponentScan使用方式

    @componentScan注解用于掃描指定路徑下的組件,并自動(dòng)將它們注冊(cè)為Spring?Bean,該注解支持多種過濾規(guī)則,可以自定義掃描過濾規(guī)則,Spring?Boot通過ConfigurationClassPostProcessor處理@ComponentScan注解,并在啟動(dòng)時(shí)創(chuàng)建和注冊(cè)BeanDefinition對(duì)象
    2025-01-01
  • SpringBoot項(xiàng)目如何把接口參數(shù)中的空白值替換為null值(推薦)

    SpringBoot項(xiàng)目如何把接口參數(shù)中的空白值替換為null值(推薦)

    這篇文章主要介紹了SpringBoot項(xiàng)目如何把接口參數(shù)中的空白值替換為null值(推薦),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • SpringBoot加載配置文件的實(shí)現(xiàn)方式總結(jié)

    SpringBoot加載配置文件的實(shí)現(xiàn)方式總結(jié)

    在實(shí)際的項(xiàng)目開發(fā)過程中,我們經(jīng)常需要將某些變量從代碼里面抽離出來,放在配置文件里面,以便更加統(tǒng)一、靈活的管理服務(wù)配置信息。所以本文將為大家總結(jié)一下SpringBoot加載配置文件的常用方式,需要的可以參考一下
    2022-03-03
  • java中&與&&的區(qū)別

    java中&與&&的區(qū)別

    本文主要介紹了java中&與&&的區(qū)別,具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • SpringBoot?Web開發(fā)之請(qǐng)求響應(yīng)、分層解耦問題記錄

    SpringBoot?Web開發(fā)之請(qǐng)求響應(yīng)、分層解耦問題記錄

    在?Spring?Boot?的?Web?請(qǐng)求響應(yīng)處理中,Servlet?起著關(guān)鍵的作用,Servlet?是?Java?Web?開發(fā)中的基本組件,主要負(fù)責(zé)處理客戶端的請(qǐng)求并生成響應(yīng),這篇文章主要介紹了SpringBoot?Web開發(fā)之請(qǐng)求響應(yīng),分層解耦,需要的朋友可以參考下
    2024-08-08
  • Spring?Boot和Vue前后端分離項(xiàng)目架構(gòu)的全過程

    Spring?Boot和Vue前后端分離項(xiàng)目架構(gòu)的全過程

    前后端分離是目前互聯(lián)網(wǎng)開發(fā)中比較廣泛使用的開發(fā)模式,主要是將前端和后端的項(xiàng)目業(yè)務(wù)進(jìn)行分離,下面這篇文章主要給大家介紹了關(guān)于Spring?Boot和Vue前后端分離項(xiàng)目架構(gòu)的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • Java泛型中的通配符舉例詳解

    Java泛型中的通配符舉例詳解

    Java泛型中的通配符是指使用"?"來表示未知類型,可以用于定義泛型類、泛型方法和泛型接口,下面這篇文章主要給大家介紹了關(guān)于Java泛型中通配符的相關(guān)資料,需要的朋友可以參考下
    2023-06-06
  • Java swing五子棋的實(shí)現(xiàn)方法

    Java swing五子棋的實(shí)現(xiàn)方法

    這篇文章主要為大家詳細(xì)介紹了Java swing五子棋的實(shí)現(xiàn)方法,Java開發(fā)圖形界面程序五子棋的實(shí)現(xiàn)方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Java接入通義千問的簡(jiǎn)單方法示例

    Java接入通義千問的簡(jiǎn)單方法示例

    ? 通義千問是阿里云開發(fā)的大語言模型(Large language Model )LLM,旨在提供廣泛的知識(shí)和普適性,可以理解和回答各領(lǐng)域中的問題,這篇文章主要給大家介紹了關(guān)于Java接入通義千問的簡(jiǎn)單方法,需要的朋友可以參考下
    2024-02-02

最新評(píng)論