Spring5源码分析容器刷新@PropertySource

编程

上一篇:Spring5 源码分析-容器刷新-配置类的嵌套类

功能说明

    将自定义的属性文件放到容器中environment.propertySources.propertySourceList集合中,供后面自动注入的时候使用@Value设置Bean的属性值

举例Demo

属性文件:

au.properties

name=Messi

age=30

au1.properties

name=HaVi

age=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

回到顶部