正文
处理BeanFactoryPostProcessor
实例化Bean
处理Bean的property注入
处理BeanPostProcessor
当然这只是比较理想的状态,实际上因为Spring Context在构造时,也需要创建很多内部的Bean,应用在接口实现里也会做自己的各种逻辑,整个流程会非常复杂。
那么占位符(${}表达式)是在什么时候被处理的?
-
实际上是在org.springframework.context.support.PropertySourcesPlaceholderConfigurer里处理的,它会访问了每一个bean的BeanDefinition,然后做占位符的处理;
-
PropertySourcesPlaceholderConfigurer实现了BeanFactoryPostProcessor接口;
-
PropertySourcesPlaceholderConfigurer的 order是Ordered.LOWEST_PRECEDENCE,也就是最低优先级的。
结合上面的Spring的生命周期,如果Bean的创建和使用在PropertySourcesPlaceholderConfigurer之前,那么就有可能出现占位符没有被处理的情况。
例子1:Mybatis 的 MapperScannerConfigurer引起的占位符没有处理
例子代码:
mybatis-demo.zip
https://github.com/hengyunabc/hengyunabc.github.io/files/1158339/mybatis-demo.zip
首先应用自己在代码里创建了一个DataSource,其中${db.user}是希望从application.properties里注入的。代码在运行时会打印出user的实际值。
@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:h2:˜/test");
ds.setUser(user);
return ds;
}
}
然后应用用代码的方式来初始化mybatis相关的配置,依赖上面创建的DataSource对象
@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();