spring里的占位符通常表现的形式是:
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="${jdbc.url}"/> </bean> 或者 @Configuration @ImportResource("classpath:/config/properties.xml") public class AppConfig { @Value("${jdbc.url}") private String url; }
Spirng在生命周期里关于Bean的处理大概可以分为下面几步:具体详见 Bean的前身今世&处理器&Aware
- 加载Bean定义(从xml或者从
@Import
等) - 处理
BeanFactoryPostProcessor
- 实例化Bean
- 处理Bean的property注入
- 处理
BeanPostProcessor
那么占位符(${}表达式)是在什么时候被处理的?
- 实际上是在
org.springframework.context.support.PropertySourcesPlaceholderConfigurer
里处理的,它会访问了每一个bean的BeanDefinition,然后做占位符的处理 -
PropertySourcesPlaceholderConfigurer
实现了BeanFactoryPostProcessor
接口 -
PropertySourcesPlaceholderConfigurer
的 order是Ordered.LOWEST_PRECEDENCE
,也就是最低优先级的
结合上面的Spring的生命周期,如果Bean的创建和使用在PropertySourcesPlaceholderConfigurer
之前,那么就有可能出现占位符没有被处理的情况。
如果在PropertySourcesPlaceholderConfigurer处理之前要用到占位符,以下方案可供参考:
- 重写PropertySourcesPlaceholderConfigurer使之处理占位符更靠前
- 在代码里,显式来处理占位符:
environment.resolvePlaceholders("${db.user}")