关于spring属性占位符用法
作者:爱艺欣聊编程
在bean定义时设置bean属性的值时,除了设置固定的值,还可以通过EL表达式和占位符来设置,容器在解析bean定义时会对EL表达式和占位符进行解析求值。
本篇来学习一下通过占位符定义属性的用法。
占位符的取值范围有三个:
- 系统变量(System.getProperty)
- 坏境变量(System.getEnv)
- 自定义的Properties文件
Spring提供了三种方式来配置加载自定义的properties:
1、PropertyPlaceholderConfigurer
一个BFPP,通过location属性把properties文件的路径传入,并且可以设置系统变量加载模式,有三种:
- 不检查系统属性;
- 优先加载自定义属性,加载不到时加载系统属性;
- 优先加载系统属性,加载不到时再加载自定义属性。通过systemPropertiesMode设置加载模式。占位符的前后缀默认是${和},但是可以通过设置placeholderPrefix和placeholderSuffix来修改前后缀。
PropertyPlaceholderConfigurer的用法如下:
bean定义xml:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>classpath:spring/beans/placeholder/attr.properties</value> </property> <property name="placeholderPrefix" value="${"></property> <property name="placeholderSuffix" value="}"></property> </bean> <bean id="placeHolderBean" class="spring.beans.placeholder.PlaceHolderBean"> <property name="id" value="${placeholder.id}"></property> <property name="name" value="${placeholder.name}"></property> <property name="refBean" ref="${placeholder.ref}"></property> </bean> <bean id="refedBean" class="spring.beans.placeholder.RefedBean"></bean>
自定义属性文件attr.properties:
placeholder.id = 123 placeholder.name = cyy placeholder.ref = refedBean
2、PropertySourcesPlaceholderConfigurer
和PropertyPlaceholderConfigurer类似,但是它不能设置系统属性加载模式,而是通过localOverride属性来决定是否用自定义的属性来覆盖系统属性。
3、context:property-placeholder标签
spring设计了context:property-placeholder标签来简化配置,它的原理跟上面两种方式是一样的,通过location属性设置属性文件路径,如有多个用逗号分隔。
容器通过PropertyPlaceholderBeanDefinitionParser解析该标签,在解析时会把这个标签解析成PropertyPlaceholderConfigurer或PropertySourcesPlaceholderConfigurer,当system-properties-mode设置为ENVIRONMENT系统变量优先时使用PropertySourcesPlaceholderConfigurer,否则使用PropertyPlaceholderConfigurer,
下面是这个标签的用法:
<context:property-placeholder location="classpath:spring/beans/placeholder/attr.properties" /> <bean id="placeHolderBean" class="spring.beans.placeholder.PlaceHolderBean"> <property name="id" value="${placeholder.id}"></property> <property name="name" value="${placeholder.name}"></property> <property name="refBean" ref="${placeholder.ref}"></property> </bean> <bean id="refedBean" class="spring.beans.placeholder.RefedBean"></bean>
属性配置器在加载完自定义属性之后会创建一个字符值处理器StringValueResolver,并且把加载到的属性设置到这个处理器中,遍历当前容器中所有的bean定义,使用这个处理来处理属性中未处理的占位符以及别名中的占位符,并且把该处理添加到容器中,为后面的bean解析提供占位符处理,见PlaceholderConfigurerSupport类中doProcessProperties方法的代码:
protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess, StringValueResolver valueResolver) { BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver); String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames(); for (String curName : beanNames) { // Check that we're not parsing our own bean definition, // to avoid failing on unresolvable placeholders in properties file locations. if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) { BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName); try { visitor.visitBeanDefinition(bd); } catch (Exception ex) { throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex); } } } // New in Spring 2.5: resolve placeholders in alias target names and aliases as well. beanFactoryToProcess.resolveAliases(valueResolver); // New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes. beanFactoryToProcess.addEmbeddedValueResolver(valueResolver); }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。