Spring5源码分析容器刷新@PropertySource
上一篇:Spring5 源码分析-容器刷新-配置类的嵌套类
功能说明
将自定义的属性文件放到容器中environment.propertySources.propertySourceList集合中,供后面自动注入的时候使用@Value设置Bean的属性值
举例Demo
属性文件:
au.properties
name=Messiage=30
au1.properties
name=HaViage=33
au2.properties
name=武磊age=33
配置类
@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截图
运行测试类输出:
武磊
- 可以使用如下配置类证明非同名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
以上是 Spring5源码分析容器刷新@PropertySource 的全部内容, 来源链接: utcz.com/z/510741.html