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

Spring中@PropertySource的使用方法和運行原理詳解

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

1 @PropertySource使用方法和運行原理機制詳解

1.1 @PropertySource簡要說明

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

1.2 @PropertySource基本使用

首先,我們用idea構(gòu)建一個Springboot項目,項目的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>

項目構(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中復用
**/
@Repeatable(PropertySources.class)
public @interface PropertySource {
 
	/**
	* 該PropertySource的名字,如果不指定會用文件名按照一定的方式生成
	**/
	String name() default "";
 
	/**
	* 指定掃描文件的路徑,可以配置多個
	**/
	String[] value();
 
	/**
	* 是否忽略文件,如果文件沒有找到,默認否,就是如果沒有文件會報錯
	**/
	boolean ignoreResourceNotFound() default false;
 
	/**
	* 指定文件編碼
	**/
	String encoding() default "";
 
	/**
	* 指定文件解析工廠
	**/
	Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
 
}

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

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

women.name=lili
women.age=18

接著我們編寫一個Women的類,并在上面通過@PropertySource的方式加載women.properties文件,同時通過@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資源目錄下面建一個文件名為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>

接著我們編寫一個Men的類,并在上面通過@PropertySource的方式加載men.xml文件,同時通過@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é)尾的配置文件

由于默認的DefaultPropertySourceFactory資源工廠并不能解析.yml或者.yaml結(jié)尾的配置文件。在此,我們先要自定義一個YAML解析的資源工廠,具體代碼實現(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)建一個YAML文件的解析工廠。
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        //2,設(shè)置資源。
        factory.setResources(encodedResource.getResource());
 
        //3,獲取解析后的Properties對象
        Properties properties = factory.getObject();
        //4返回。此時不能像默認工廠那樣返回ResourcePropertySource對象 ,要返回他的父類PropertiesPropertySource對象。
        return name != null ? new PropertiesPropertySource(name, properties) :
                new PropertiesPropertySource(encodedResource.getResource().getFilename(),properties);
    }
}

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

person:
  name: zhangsan
  address: shanghaihsi

接著我們編寫一個Person的類,并在上面通過@PropertySource的方式加載person.yml文件,在配置文件的同時要指定資源文件的解析工廠類,這里我們指定為YAMLPropertySourceFactory.class。同時通過@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é)尾的配置文件

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

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

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

接著我們編寫一個Other的類,并在上面通過@PropertySource的方式加載other.xxx文件,在配置文件的同時要指定資源文件的編碼,這里我們指定為utf-8。同時通過@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 測試

在啟動類下面注入上面例子中的Bean,在容器啟動成功后打印相關(guān)數(shù)據(jù),具體實現(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);
    }
}

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

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

1.3 @PropertySource使用小結(jié)

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

1.4 @PropertySource運行原理機制

源碼的啟動過程比較復雜和繁瑣,由于篇幅有限,在這里,我們就不追代碼,直接定位到對應的處理邏輯代碼上。

我們定位到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);
                //實際處理邏輯
				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的使用方法和運行原理詳解的文章就介紹到這了,更多相關(guān)@PropertySource的使用方法和運行原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

衡阳县| 京山县| 慈利县| 新密市| 灌南县| 共和县| 安吉县| 锦屏县| 温宿县| 尼勒克县| 营口市| 泰州市| 阿拉善盟| 邯郸县| 正镶白旗| 西青区| 丁青县| 秦安县| 咸阳市| 和田县| 武鸣县| 洪湖市| 海阳市| 珲春市| 建德市| 伊宁市| 贵定县| 松阳县| 哈巴河县| 邓州市| 华亭县| 鹰潭市| 河北省| 惠水县| 隆化县| 噶尔县| 东山县| 闻喜县| 自贡市| 运城市| 五河县|