ClassPathXmlApplicationContext源码解析三:BFPP
来源:互联网 发布:网络交友的利弊 编辑:程序博客网 时间:2024/06/05 10:29
本文引自我的个人博客: 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}
- ClassPathXmlApplicationContext源码解析三:BFPP
- ClassPathXmlApplicationContext 源码解析
- ClassPathXmlApplicationContext源码解析四
- ClassPathXmlApplicationContext源码解析一:准备工作
- Spring IOC 源码-ClassPathXmlApplicationContext-bean解析
- ClassPathXmlApplicationContext源码解析五:加载单例
- ClassPathXmlApplicationContext源码解析二:默认空间元素解析
- Spring4源码分析(ClassPathXmlApplicationContext)
- Spring 源码梳理(一) ClassPathXmlApplicationContext
- AFNetworking源码解析<三>
- TFS源码解析三
- AFNetworking源码解析<三>
- AFNetworking源码解析<三>
- AFNetworking源码解析<三>
- AFNetworking源码解析<三>
- AFNetworking源码解析<三>
- AFNetworking源码解析<三>
- AFNetworking源码解析<三>
- 定位与css选择器
- JS获取填报扩展单元格控件的值
- [复习][poj2001]字典树(trie树)Shortest Prefixes
- 博弈搜索练习--POJ-2003 Hire and Fire
- Spring Boot中使用Swagger2构建强大的RESTful API文档
- ClassPathXmlApplicationContext源码解析三:BFPP
- Linux 常用基本命令 cat grep
- SpringMVC基本配置
- 青蛙跳和斐波那契数列(转)
- vim的常用指令
- 单链表翻转
- ubutun下的一些使用小技巧
- Java通过JNI调用本地C/C++程序--常用示例
- Console MP3播放器 for C++