摘自
Environment
注释:Properties play an important role in almost all applications, and may originate from a variety of sources: properties files, JVM system properties, system environment variables, JNDI, servlet context parameters, ad-hoc Properties objects, Maps, and so on. The role of the environment object with relation to properties is to provide the user with a convenient service interface for configuring property sources and resolving properties from them.
配置
XML方式
这种应该是最常见的方式了,在spring
配置文件中:
1 | <context:property-placeholder location="classpath:bean.properties" /> |
注解方式
如果不是用xml
方式,也可以使用注解方式,使用@PropertySource
:
1 |
|
其他方式
PropertyPlaceholderConfigurer
XML方式:
1 | <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> |
注解方式:
1 |
|
PropertySourcesPlaceholderConfigurer
XML方式:
1 | <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> |
注解方式:
1 |
|
使用
XML
1 | <bean id="dataSource"> |
@Value
1 | "${jdbc.url}") ( |
Environment
1 |
|
实现
PropertySourcesPlaceholderConfigurer
在看实现xml
中占位符替换之前,先看下PropertySourcesPlaceholderConfigurer
继承关系:
可以看到PropertySourcesPlaceholderConfigurer
实现了BeanFactoryPostProcessor
,而其中的postProcessBeanFactory()
方法可以对BeanDefinition
做属性更改:
1 | // PropertySourcesPlaceholderConfigurer.java |
可以看到PropertySourcesPlaceholderConfigurer
在处理配置文件时,并没有将配置文件加入到environment
,而是自己内部进行维护propertySource
,因此无法通过environment
中获取到配置文件内容
1 | // PlaceholderConfigurerSupport.java |
我们知道,Spring
在注册Bean
时会先将Bean
转化为BeanDefinition
,而这个BeanDefinition
是未做任何属性上的处理(以例子来说,PropertiesService.name
的值就是${properties.name}
),而BeanDefinitionVisitor
做的事就是将BeanDefinition
的相关属性值做占位符替换处理
1 | public class BeanDefinitionVisitor { |
可以看到visitBeanDefinition()
对很多属性都做了占位符替换,每个属性替换方法实现都类似。以例子来说,通过构造方法属性注入,所以看visitGenericArgumentValues()
,该方法实现也是比较简单,循环获取每个属性对应的属性值(${properties.name}
),然后调用PropertyResolver
实现占位符替换,最后对属性重新设值
context:property-placeholder
context:property-placeholder
看下解析注册部分,因为占位符替换逻辑其实就是通过注册PropertySourcesPlaceholderConfigurer
实现,部分代码如下:
1 | // AbstractBeanDefinitionParser.java |
parseInternal()
在子类AbstractSingleBeanDefinitionParser
中实现:
1 | // AbstractSingleBeanDefinitionParser.java |
看下getBeanClass()
方法,决定了AbstractBeanDefinition
类型:
1 | // PropertyPlaceholderBeanDefinitionParser.java |
在BeanFactory
中注册了PropertySourcesPlaceholderConfigurer
之后,占位符替换的逻辑就和上面一样了
@PropertySources
ConfigurationClassParser
在注解启动时(使用@Configuration
)是一个非常重要的类,功能就是解析使用@Configuration
的配置类,包括@PropertySources
,@ComponentScan
等类注解,以及@Bean
等方法注解,此处看下@PropertySources
解析:
1 | // ConfigurationClassParser.java |
因此,在这种配置下,资源文件中的内容可以通过注入Environment
获取:
1 |
|