# BeanFactoryPostProcessor
BeanFactoryPostProcessor类是spring提供的可以对application context中的bean definition进行自定义修改的的后处理接口。 BeanFactoryPostProcessor只能修改BeanDefinition即Bean的定义,如果要修改bean实例,需要使用BeanPostProcessor。 相当于自定义一些Bean的定义,比如@Configuration、MyBatis的Mapper Bean都是使用BeanFactoryPostProcessor以及子接口BeanDefinitionRegistryPostProcessor实现的。
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
2
3
4
5
6
7
8
9
10
11
12
BeanDefinitionRegistryPostProcessor提供的postProcessBeanDefinitionRegistry方法可以在BeanFactoryPostProcessor的postProcessBeanFactory执行之前 注册bean definition。
BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor的调用时机,是在AbstractApplicationContext的refresh方法中, 在DispatcherServlet init的时候,就会创建ApplicationContext并调用refresh方法。 refresh方法中invokeBeanFactoryPostProcessors(beanFactory)是调用application context中注册的BeanFactoryPostProcessor。(前面的postProcessBeanFactory 是给AbstractApplicationContext子类留下的扩展方法,比如ServletWebServerApplicationContext会增加一些BeanPostProcessor。)
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
invokeBeanFactoryPostProcessors中,会先调用BeanFactoryPostProcessor的postProcessBeanDefinitionRegistry再调用postProcessBeanFactory。
# 常见实现
# ConfigurationClassPostProcessor
ConfigurationClassPostProcessor用来实现@Configuration注解的功能。 通过@Configuration注解,可以通过代码声明bean定义。
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
// instantiate, configure and return bean ...
}
}
2
3
4
5
6
7
8
ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口, 通过ConfigurationClassParser类解析@Configuration注解标识的类中的@ComponentScan、@Bean方法定义、@Import(ImportBeanDefinitionRegistrar)等注解,向 通过ConfigurationClassParser解析完成后,ConfigurationClassPostProcessor就会在postProcessBeanDefinitionRegistry的时候将 解析出来的BeanDefinition注册到BeanFactory中。
# MapperScannerConfigurer
MapperScannerConfigurer是spring-mybatis中将Mapper接口注册为spring中的bean的BeanDefinitionRegistryPostProcessor 使用方式是定义一个MapperScannerConfigurer的bean。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.mybatis.spring.sample.mapper" />
<!-- optional unless there are multiple session factories defined -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
2
3
4
5
MapperScannerConfigurer会在postProcessBeanDefinitionRegistry的时候创建一个ClassPathMapperScanner(继承自spring内部的ClassPathBeanDefinitionScanner) 这个Scanner可以设置bean的配置比如有什么注解或继承什么接口的是MyBatis的Mapper类,通过Scanner扫描出来BeanDefinition后, 会设置一些FactoryBean、sqlSessionTemplateBeanName等 帮助创建MapperFactoryBean的属性,然后通过BeanFactory注册BeanDefinition。
另外注意spring mybatis也提供了通过在Configuration类上增加@MapperScan或@MapperScans来扫描bean的功能,功能上和MapperScannerConfigurer一致但是使用更简单。 @MapperScan是通过MapperScannerRegistrar也就是通过上面提到的ConfigurationClassPostProcessor机制来实现的。
# PropertyPlaceholderConfigurer&PropertyOverrideConfigurer
PropertyPlaceholderConfigurer、PropertyOverrideConfigurer能够替换bean定义中的${}占位符,替换为环境变量、properties文件中的值,比如替换数据库的配置等等