Spring5 源碼分析-容器刷新-@PropertySource

上一篇:Spring5 源碼分析-容器刷新-配置類的嵌套類java

功能說明

    將自定義的屬性文件放到容器中environment.propertySources.propertySourceList集合中,供後面自動注入的時候使用@Value設置Bean的屬性值spring

舉例Demo

屬性文件:框架

au.properties源碼分析

name=Messi
age=30

au1.properties測試

name=HaVi
age=33

au2.propertiesthis

name=武磊
age=33

配置類spa

@Configuration
@ComponentScan("com.jv.spring.nestedclass.scan")
@PropertySource(value = "classpath:au1.properties",name="my-au1",encoding = "utf-8")
public class NestedConfig {
	/*@ComponentScan("com.jv.spring.nestedclass.scan")
	@PropertySource("classpath:au.properties")
	class InnerConfig{

	}*/
}

測試類操作系統

public class NestedMain {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(NestedConfig.class);
		NestedUser bean = ac.getBean(NestedUser.class);
		System.out.println(bean.getName());
	}
}

源碼分析

// Process any @PropertySource annotations  處理@PropertySource註解的類
		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");
			}
		}
private void addPropertySource(PropertySource<?> propertySource) {
		String name = propertySource.getName();
		MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();

		//若是存在同名的PropertySource,則使用CompositePropertySource替換原來的PropertySource,而CompositePropertySource中包含了全部的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) {
					//將新的PropertySource添加到第一個,使用時在該組中最後一個使用。
					((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;
			}
		}
		/**
		 * 若是沒有同名的PropertySource,當只有一個的時候,直接添加到propertySources中
		 * 不然將新的PropertySource添加到除systemProperties systemEnvironment變量緊接着的第一個(意思就是後添加的後使用,可是若是他們存在同名的屬性,後使用的PropertySource會覆蓋先使用的)
		 */
		if (this.propertySourceNames.isEmpty()) {
			propertySources.addLast(propertySource);
		}
		else {
			/**
			 * propertySourceNames中存放的是自定義的PropertySource name,不包含systemProperties systemEnvironment
			 * 所以每次添加的新PropertySource都是在列表中的第三個(得出此結論的前提框架不在添加其餘默認的PropertySource)
			 */
			String firstProcessed = this.propertySourceNames.get(this.propertySourceNames.size() - 1);
			propertySources.addBefore(firstProcessed, propertySource);
		}
		this.propertySourceNames.add(name);
	}
  • 可使用以下配置類證實同名PropertySource最後只有一個組合CompositePropertySource。注意同名,能夠不一樣文件的。
@Configuration
@ComponentScan("com.jv.spring.nestedclass.scan")
@PropertySource(value = "classpath:au.properties",name="my-au",encoding = "utf-8")
@PropertySource(value = "classpath:au1.properties",name="my-au",encoding = "utf-8")
@PropertySource(value = "classpath:au2.properties",name="my-au",encoding = "utf-8")
public class NestedConfig {

}

DEBUG截圖.net

運行測試類輸出:3d

武磊

 

  • 可使用以下配置類證實非同名PropertySource,後添加的後使用
@Configuration
@ComponentScan("com.jv.spring.nestedclass.scan")
@PropertySource(value = "classpath:au.properties",name="my-au",encoding = "utf-8")
@PropertySource(value = "classpath:au1.properties",name="my-au1",encoding = "utf-8")
@PropertySource(value = "classpath:au2.properties",name="my-au2",encoding = "utf-8")
public class NestedConfig {
	/*@ComponentScan("com.jv.spring.nestedclass.scan")
	@PropertySource("classpath:au.properties")
	class InnerConfig{

	}*/
}

 

輸出內容是:

武磊

附:若是我在操做系統的環境變量中增長name=伊布,重啓Idea,運行程序輸出的結果是:

 

留給你們本身去思考,爲何輸出的是「伊布」,從結果反推回去能獲得一個什麼結論。

再留一個思考題:可否自定義一個PropertySource晚於systemProperties或者systemEnvironment使用,若是不能夠,那如何才能覆蓋它們兩種設置的值喃?

 

下一篇:Spring5 源碼分析-容器刷新-@ComponentScan

相關文章
相關標籤/搜索