本文引自我的个人博客: sunmingshuai.coding.me
让我们再回到refresh()
方法 继续往下看 看下面两个方法
...
//如果是XmlWebApplicationContext的话 会注册一些BPP 例如ServletContextAwareProcessor
// 这里留空
postProcessBeanFactory(beanFactory);
// spring扩展的实现(容器级别) BeanFactoryPostProcessor 在实例化任何用户定义的bean之前 会首先调用BFPP的接口方法
// 常见的BFPP:PropertyPlaceholderConfigurer
invokeBeanFactoryPostProcessors(beanFactory);
...
//BFPP接口
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
invokeBeanFactoryPostProcessors
方法逻辑就比较简单了 就是调用BFPP
的接口方法 这些BFPP
的来源途径有
1. 硬编码方式
2. 用户配置
3. 容器自身为了完成某些功能添加
这些BFPP支持排序 排序大的先调用
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//BFPP(postProcessBeanFactory)
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
//BeanDefinitionRegistryPostProcessor 是BFPP的子类
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
new LinkedList<BeanDefinitionRegistryPostProcessor>();
//硬编码方式加入的BFPP 例如通过addXXX
for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryPostProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
registryPostProcessors.add(registryPostProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
//处理配置中的BDRPP
Map<String, BeanDefinitionRegistryPostProcessor> beanMap =
beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
OrderComparator.sort(registryPostProcessorBeans);
for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
processedBeans.addAll(beanMap.keySet());
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
OrderComparator.sort(priorityOrderedPostProcessors);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
OrderComparator.sort(orderedPostProcessors);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
}
上面的代码逻辑很简单 就不再解释了 下面我们介绍一个常用的BFPP
: PropertyPlaceholderConfigurer
先看一下常用的配置
<bean name="official" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="100" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="locations">
<list>
<value>file:${user.home}/config/official.properties</value>
</list>
</property>
</bean>
PropertyPlaceholderConfigurer
是用来在BeanClass
实例化之前调用的,通过载入指定properties文件,替换诸如${}
这种形式的变量.PropertyPlaceholderConfigurer
可以用来区分生产环境与开发环境 例如我们在生产环境部署official.properties
文件 这个文件中的参数值 如jdbc.url
代表的是生产环境的value
然后我们在开发环境中部署developer.properties
文件 这个文件中的参数值 如jdbc.url
代表的是开发环境的value
这样我们的项目发布在什么环境读取的就是相应环境的变量值 不需要每次改代码去解决
PropertyPlaceholderConfigurer
的功能实现我们大概能猜的到 首先肯定是先获取这个Bean
这个步骤会涉及到Bean
的实例化 属性填充等操作 我们暂且略过这个步骤 后面会详细介绍 然后就是读取配置的properties
文件 再然后就是替换Bean
属性中的${xx}