Spring里的占位符
spring里的占位符凡是表示的形式是:
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="${jdbc.url}"/>
</bean>
可能
@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
@Value("${jdbc.url}")
private String url;
}
Spring应用在有时会呈现占位符设置没有注入,原因大概是多样的。
本文先容两种较量巨大的环境。
占位符是在Spring生命周期的什么时候处理惩罚的
Spirng在生命周期里关于Bean的处理惩罚或许可以分为下面几步:

虽然这只是较量抱负的状态,实际上因为Spring Context在结构时,也需要建设许多内部的Bean,应用在接话柄现里也会做本身的各类逻辑,整个流程会很是巨大。
那么占位符(${}表达式)是在什么时候被处理惩罚的?
团结上面的Spring的生命周期,假如Bean的建设和利用在PropertySourcesPlaceholderConfigurer之前,那么就有大概呈现占位符没有被处理惩罚的环境。
例子1:Mybatis 的 MapperScannerConfigurer引起的占位符没有处理惩罚
例子代码:mybatis-demo.zip
@Configuration
public class MyDataSourceConfig {
@Bean(name = "dataSource1")
public DataSource dataSource1(@Value("${db.user}") String user) {
System.err.println("user: " + user);
JdbcDataSource ds = new JdbcDataSource();
ds.setURL("jdbc:p:˜/test");
ds.setUser(user);
return ds;
}
}
@Configuration
public class MybatisConfig1 {
@Bean(name = "sqlSessionFactory1")
public SqlSessionFactory sqlSessionFactory1(DataSource dataSource1) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
org.apache.ibatis.session.Configuration ibatisConfiguration = new org.apache.ibatis.session.Configuration();
sqlSessionFactoryBean.setConfiguration(ibatisConfiguration);
sqlSessionFactoryBean.setDataSource(dataSource1);
sqlSessionFactoryBean.setTypeAliasesPackage("sample.mybatis.domain");
return sqlSessionFactoryBean.getObject();
}
@Bean
MapperScannerConfigurer mapperScannerConfigurer(SqlSessionFactory sqlSessionFactory1) {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory1");
mapperScannerConfigurer.setBasePackage("sample.mybatis.mapper");
return mapperScannerConfigurer;
}
}
今世码运行时,软件开发,输出功效是:
user: ${db.user}
为什么会user这个变量没有被注入?
阐明下Bean界说,可以发明MapperScannerConfigurer它实现了BeanDefinitionRegistryPostProcessor。这个接口在是Spring扫描Bean界说时会回调的,远早于BeanFactoryPostProcessor。
所以原因是:
要办理这个问题,可以在代码里,显式来处理惩罚占位符:
environment.resolvePlaceholders("${db.user}")
例子2:Spring boot自身实现问题,导致Bean被提前初始化
例子代码:demo.zip