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

相关文章
相关标签/搜索