Spring加载配置文件多种方式(@PropertySource等)

Spring加载配置文件多种方式(@PropertySource等)

可以基于xml或纯java配置, 源码分析基于Spring 5.2.5, 为了简洁会省去部分源码.

本文章讲的是properties文件. 顺带一提, 在spring引入xml文件:<import>或@ImportResource

方式一: @PropertySource

// 该例子来自于源码, 引入的后的properties文件也可以通过@Value("${}")使用
@Configuration
@PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
public class AppConfig {
        @Autowired
        Environment env;

        @Bean
        public TestBean testBean() {
        TestBean testBean = new TestBean();
        testBean.setName(env.getProperty("testbean.name"));
        return testBean;
	}
}

@PropertySource由ConfigurationClassParser处理, 并生成PropertySource(ResourcePropertySource), 添加到Environment(StandardServletEnvironment)(参考第18行)

class ConfigurationClassParser {
	protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {
		// Process any @PropertySource annotations
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
		}
    }

    private void addPropertySource(PropertySource<?> propertySource) {
        MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment).getPropertySources();
        //...
        propertySources.addLast(propertySource);
    }
    
}

注意, 对于springboot是通过EnvironmentPostProcessor(ConfigDataEnvironmentPostProcessor)处理配置文件(application.properties/yml等), 最终同样是生成PropertySource(OriginTrackedMapPropertySource), 添加到Environment(ApplicationServletEnvironment).

具体加载方式参考:YamlPropertySourceLoaderPropertiesPropertySourceLoader.

(基于源码springboot 2.7.2)

方式二: <context:property-placeholder>

<context:property-placeholder location="my.properties" />

该方式会由**PropertySourcesPlaceholderConfigurer**处理(该类本身也是spring管理), 并生成PropertySource(PropertiesPropertySource), 并保存(第22行的mergeProperties()加载location)

注意使用该标签后, 上述的Environment也会被添加到该类(第11行).

public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerSupport implements EnvironmentAware {
    
	private MutablePropertySources propertySources;
	private PropertySources appliedPropertySources;
	private Environment environment;
    
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		if (this.propertySources == null) {
			this.propertySources = new MutablePropertySources();
			if (this.environment != null) {
				this.propertySources.addLast(
					new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) {
						@Override
						public String getProperty(String key) {
							return this.source.getProperty(key);
						}
					}
				);
			}
			try {
				PropertySource<?> localPropertySource =
						new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties());
				if (this.localOverride) {
					this.propertySources.addFirst(localPropertySource);
				}
				else {
					this.propertySources.addLast(localPropertySource);
				}
			}
			catch (IOException ex) {
				throw new BeanInitializationException("Could not load properties", ex);
			}
		}
		// 处理占位符"${}", 为beanFactory添加StringValueResolver等
        // 参考:AbstractBeanFactory#resolveEmbeddedValue
		processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
		this.appliedPropertySources = this.propertySources;
	}    
    // 从这里可以获取所有的PropertySource(MutablePropertySources)
    public PropertySources getAppliedPropertySources() throws IllegalStateException {
		return this.appliedPropertySources;
	}
}

注意在springboot中该类在PropertyPlaceholderAutoConfiguration生成

在传统spring中该类在ContextNamespaceHandler->PropertyPlaceholderBeanDefinitionParser生成

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值