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

Spring中的@PropertySource注解源碼詳解

 更新時(shí)間:2023年11月14日 10:35:05   作者:drunk in spring  
這篇文章主要介紹了Spring中的@PropertySource注解源碼詳解,@PropertySource注解用于指定資源文件讀取的位置,它不僅能讀取properties文件,也能讀取xml文件,并且通過yaml解析器,配合自定義PropertySourceFactory實(shí)現(xiàn)解析yaml文件,需要的朋友可以參考下

@PropertySource注解使用

@PropertySource注解用于指定資源文件讀取的位置,它不僅能讀取properties文件,也能讀取xml文件,并且通過yaml解析器,配合自定義PropertySourceFactory實(shí)現(xiàn)解析yaml文件

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
	//資源名稱,為空則根據(jù)資源的描述符生成
	String name() default "";
	/**
	 *資源路徑
	 *classpath:application.properties
	 *file:/
	 */
	String[] value();
	//是否忽略資源不存在的情況,如果不忽略,當(dāng)資源不存在時(shí)報(bào)錯(cuò)
	boolean ignoreResourceNotFound() default false;
	//指定資源文件的編碼格式
	String encoding() default "";
	//資源工廠
	Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}

源碼解析

在bean實(shí)例化之前有一個(gè)ConfigurationClassPostProcessor類,會(huì)操作BeanDefinition并且加入到BeanDefinitionRegistry中,它的優(yōu)先級(jí)在所有的BeanDefinitionRegistryPostProcessor里面是最低的。

優(yōu)先級(jí):最低

public int getOrder() {
	return Ordered.LOWEST_PRECEDENCE;  // within PriorityOrdered
}

會(huì)在這個(gè)類中進(jìn)行相關(guān)注解的解析操作,在進(jìn)行@PropertySource注解解析的時(shí)候要借助ConfigurationClassParser的parse方法

在進(jìn)行@PropertySource注解解析之前,需要拿到兩個(gè)對(duì)象ConfigurationClass和SourceClass

bean的元數(shù)據(jù)信息(bd.getMetadata),和beanName,封裝成ConfigurationClass對(duì)象

new ConfigurationClass(metadata, beanName)

SourceClass這個(gè)對(duì)象理解為跟類或者接口對(duì)應(yīng),然后把metadata對(duì)象包裝進(jìn)去

SourceClass sourceClass = asSourceClass(configClass, filter);

接下來(lái)正式進(jìn)入解析流程

for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
		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");
	}
}

拿到類上面的所有PropertySource注解的值A(chǔ)nnotationAttributes,放到processPropertySource方法中進(jìn)行解析

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對(duì)象
			Resource resource = this.resourceLoader.getResource(resolvedLocation);
			//加載Resource中的配置屬性封裝成Properties對(duì)象中,并創(chuàng)建PropertySource對(duì)象加入到Environment對(duì)象中
			addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
		}
		catch (IllegalArgumentException | FileNotFoundException | UnknownHostException 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;
			}
		}
	}
}

這里看一下createPropertySource方法,就是將配置文件中的內(nèi)容封裝成ResourcePropertySource對(duì)象,作為屬性源

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

屬性源拿到之后,要統(tǒng)一交給Environment管理,調(diào)用addPropertySource方法

private void addPropertySource(PropertySource<?> propertySource) {
	String name = propertySource.getName();
	//獲取Environment對(duì)象中的MutablePropertySources
	MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();

	//如果已經(jīng)存在了該配置文件的PropertySource則合并久的
	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();
				}
				//其實(shí)就是CompositePropertySource里面有一個(gè)Set,Set里面裝了新和舊的PropertySource對(duì)象
				CompositePropertySource composite = new CompositePropertySource(name);
				composite.addPropertySource(newSource);
				composite.addPropertySource(existing);
				propertySources.replace(name, composite);
			}
			return;
		}
	}

	if (this.propertySourceNames.isEmpty()) {
		propertySources.addLast(propertySource);
	}
	else {
		//用于計(jì)算插入的位置index
		String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
		//吧propertySource對(duì)象存入MutablePropertySources的list中
		propertySources.addBefore(firstProcessed, propertySource);
	}
	this.propertySourceNames.add(name);
}

拿到Environment中的MutablePropertySources,用來(lái)放置拿到的屬性源。 如果有相同的屬性源,則升級(jí)成CompositePropertySource,把新舊相同的屬性源進(jìn)行合并,再放到MutablePropertySources中

看看CompositePropertySource類的內(nèi)部 有Set<PropertySource<?>> propertySources = new LinkedHashSet<>();用來(lái)放置屬性源 也重寫了getProperty方法

public Object getProperty(String name) {
	for (PropertySource<?> propertySource : this.propertySources) {
		Object candidate = propertySource.getProperty(name);
		if (candidate != null) {
			return candidate;
		}
	}
	return null;
}

@PropertySource注解中配置的屬性源都交給Environment管理

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

相關(guān)文章

  • Spring Boot Web 開發(fā)注解篇

    Spring Boot Web 開發(fā)注解篇

    在 Spring Boot 快速入門中,只要在 pom.xml 加入了 spring-boot-starter-web 依賴,即可快速開發(fā) web 應(yīng)用。下文給大家詳細(xì)介紹了spring boot web 開發(fā)注解,感興趣的朋友參考下吧
    2017-08-08
  • 微信隨機(jī)生成紅包金額算法java版

    微信隨機(jī)生成紅包金額算法java版

    這篇文章主要為大家詳細(xì)介紹了java和php版的微信隨機(jī)生成紅包金額算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • Java多種文件復(fù)制方式以及效率對(duì)比分析

    Java多種文件復(fù)制方式以及效率對(duì)比分析

    本文總結(jié)了Java復(fù)制文件的多種方式,包括傳統(tǒng)的字節(jié)流、字符流、NIO系列、第三方包中的FileUtils等,并提供了不同方式的效率比較,同時(shí),還介紹了遍歷文件和文件夾的方法,并使用Swing進(jìn)行了簡(jiǎn)單的圖形界面展示,通過實(shí)際測(cè)試,對(duì)比了不同方法的性能,提供了參考
    2025-11-11
  • Java中Date時(shí)區(qū)的轉(zhuǎn)換代碼示例

    Java中Date時(shí)區(qū)的轉(zhuǎn)換代碼示例

    這篇文章主要給大家介紹了關(guān)于Java中Date時(shí)區(qū)轉(zhuǎn)換的相關(guān)資料,當(dāng)在不同的時(shí)區(qū)使用相同程序,時(shí)間的值只會(huì)為當(dāng)?shù)貢r(shí)間,這樣就會(huì)造成時(shí)間混亂,需要的朋友可以參考下
    2023-07-07
  • java基于UDP實(shí)現(xiàn)圖片群發(fā)功能

    java基于UDP實(shí)現(xiàn)圖片群發(fā)功能

    這篇文章主要為大家詳細(xì)介紹了java基于UDP實(shí)現(xiàn)圖片群發(fā)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 解決使用stream將list轉(zhuǎn)map時(shí),key重復(fù)導(dǎo)致報(bào)錯(cuò)的問題

    解決使用stream將list轉(zhuǎn)map時(shí),key重復(fù)導(dǎo)致報(bào)錯(cuò)的問題

    這篇文章主要介紹了解決使用stream將list轉(zhuǎn)map時(shí),key重復(fù)導(dǎo)致報(bào)錯(cuò)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • JAVA實(shí)現(xiàn)賬戶取款和存款操作

    JAVA實(shí)現(xiàn)賬戶取款和存款操作

    這篇文章主要介紹了JAVA實(shí)現(xiàn)賬戶取款和存款操作,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • spring中@value注解需要注意的問題

    spring中@value注解需要注意的問題

    本篇文章主要介紹了spring中@value注解需要注意的問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2017-03-03
  • MyBatis的SUM映射問題及解決

    MyBatis的SUM映射問題及解決

    這篇文章主要介紹了MyBatis的SUM映射問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java中的UrlDecoder 和 UrlEncoder_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java中的UrlDecoder 和 UrlEncoder_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    HTML 格式編碼的實(shí)用工具類。該類包含了將 String 轉(zhuǎn)換為 application/x-www-form-urlencoded MIME 格式的靜態(tài)方法。下文通過實(shí)例代碼給大家介紹Java中的UrlDecoder 和 UrlEncoder知識(shí),感興趣的的朋友一起看看吧
    2017-07-07

最新評(píng)論

黄陵县| 观塘区| 阿克陶县| 南陵县| 蕲春县| 义马市| 依兰县| 城步| 鹿泉市| 万宁市| 将乐县| 满洲里市| 文昌市| 松桃| 昌宁县| 长武县| 治县。| 大城县| 和顺县| 太原市| 青浦区| 四会市| 牟定县| 普兰县| 高邑县| 林周县| 大竹县| 上林县| 崇信县| 永登县| 五台县| 洛隆县| 涞源县| 江达县| 肥城市| 安远县| 黎川县| 额尔古纳市| 潢川县| 调兵山市| 台南县|