Spring源码解析笔记9——容器的功能扩展BeanFactory的后处理(BeanFactoryPostProcessor)
2018-01-31 14:27
796 查看
BeanFactoryPostProcessor接口跟BeanPostProcessor类似,可以对bean的定义(配置元数据)进行处理。SpringIoc容器允许BeanFactoryPostProcessor在容器实际实例化任何其他的bean之前读取配置元数据,并有可能修改它。
如果想改变实际的bean实例(例如从配置元数据创建的对象),那么最好使用BeanPostProcessor。
BeanFactoryPostProcessor的作用域范围是容器级的。它只和你所使用的容器有关。如果你在容器中定义了一个BeanFactoryPostProcessor,它仅仅对此容器中的bean进行后处理。BeanFactoryPostProcessor不会对定义在另一个容器中的bean进行后处理,即使这两个容器都在同一层次。
1.BeanFactoryPostProcessor的典型应用:PropertyPlaceholderConfigurer
propertyConfigurer只不过是Spring框架管理的一个bean,并没有被bean或者对象引用,Spring的beanFactory是怎么知道要从这个bean 中获取配置信息呢?
PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessor接口,当spring加载任何实现了这个接口的bean的配置时,都会在bean工厂载入所有bean的配置之后执行postProcessBeanFactory方法。
PropertyResourceConfigurer类中实现了postProcessFactory方法,在方法中先后调用了mergeProperties,convertProperties,processorProperties这三个方法。分别得到配置,将得到的配置转换为合适的类型,最后将配置内容告知BeanFactory。
2.使用自定义BeanFactoryPostProcessor
配置文件BeanFactory.xml
ObscenityRemovingBeanFactoryPostProcessor类:
测试代码:
运行结果:
3.激活BeanFactoryPostProcessor
继续跟踪refresh方法中的this.invokeBeanFactoryPostProcessors(beanFactory)方法(在上一篇文章里面——笔记8中):
4.注册BeanPostProcessor,继续跟踪refresh方法中的registerBeanPostProcessors(beanFactory)方法(在上一篇文章里面——笔记8中):
如果想改变实际的bean实例(例如从配置元数据创建的对象),那么最好使用BeanPostProcessor。
BeanFactoryPostProcessor的作用域范围是容器级的。它只和你所使用的容器有关。如果你在容器中定义了一个BeanFactoryPostProcessor,它仅仅对此容器中的bean进行后处理。BeanFactoryPostProcessor不会对定义在另一个容器中的bean进行后处理,即使这两个容器都在同一层次。
1.BeanFactoryPostProcessor的典型应用:PropertyPlaceholderConfigurer
<!--xml配置文件中加入以下代码--> <bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>jdbc.properties</value> </property> <property name="fileEncoding"> <value>UTF-8</value> </property> </bean>
#jdbc.properties文件内容 jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://192.168.1.105:3306/msmk1231?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=UTF-8 jdbc.username=mysql jdbc.password=mysql
<!--spring配置文件中使用外部文件的值--> <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" > <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean>
propertyConfigurer只不过是Spring框架管理的一个bean,并没有被bean或者对象引用,Spring的beanFactory是怎么知道要从这个bean 中获取配置信息呢?
PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessor接口,当spring加载任何实现了这个接口的bean的配置时,都会在bean工厂载入所有bean的配置之后执行postProcessBeanFactory方法。
PropertyResourceConfigurer类中实现了postProcessFactory方法,在方法中先后调用了mergeProperties,convertProperties,processorProperties这三个方法。分别得到配置,将得到的配置转换为合适的类型,最后将配置内容告知BeanFactory。
2.使用自定义BeanFactoryPostProcessor
配置文件BeanFactory.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="bfpp" class="cn.partner4java.beanfactorypostprocessor.ObscenityRemovingBeanFactoryPostProcessor"> <property name="obscenities"> <set> <value>winky</value> <value>bum</value> </set> </property> </bean> <bean id="simpleBean" class="cn.partner4java.beanfactorypostprocessor.SimpleBean"> <property name="connectionString" value="bollocks"/> <property name="password" value="winky"/> <property name="username" value="bum"/> </bean> </beans>
ObscenityRemovingBeanFactoryPostProcessor类:
class ObscenityRemovingBeanFactoryPostProcessor implements BeanFactoryPostProcessor { /** bean的名称 */ private String name; /** 注册过滤文字 */ private Set<String> obscenities; public ObscenityRemovingBeanFactoryPostProcessor() { this.obscenities = new HashSet<String>(); } /** * 主要业务处理。 */ public void postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory) throws BeansException { String[] beanNames = beanFactory.getBeanDefinitionNames(); for(String beanName:beanNames){ BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); StringValueResolver valueResolver = new StringValueResolver() { public String resolveStringValue(String strVal) { if(isObscene(strVal)){ 10692 return "****"; } return strVal; } }; BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver); visitor.visitBeanDefinition(beanDefinition); } } private boolean isObscene(Object value) { String potentialObscenity = value.toString().toUpperCase(); return this.obscenities.contains(potentialObscenity); } public void setObscenities(Set<String> obscenities) { this.obscenities.clear(); for(String obscentity:obscenities){ this.obscenities.add(obscentity.toUpperCase()); } } }
测试代码:
ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("/META-INF/Beanfactory.xml")); BeanFactoryPostProcessor bfpp = (BeanFactoryPostProcessor)beanFactory.getBean("bfpp"); bfpp.postProcessBeanFactory(beanFactory); System.out.println(beanFactory.getBean("simpleBean"));
运行结果:
SimpleBean{password='****', username='****', connectionString='bollocks'}
3.激活BeanFactoryPostProcessor
继续跟踪refresh方法中的this.invokeBeanFactoryPostProcessors(beanFactory)方法(在上一篇文章里面——笔记8中):
public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>(); List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; registryProcessor.postProcessBeanDefinitionRegistry(registry); registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); } } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); reiterate = true; } } sortPostProcessors(currentRegistryProcessors, beanFactory); registryProcessors.addAll(currentRegistryProcessors); invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); currentRegistryProcessors.clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, 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<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // Clear cached merged bean definitions since the post-processors might have // modified the original metadata, e.g. replacing placeholders in values... beanFactory.clearMetadataCache(); }
4.注册BeanPostProcessor,继续跟踪refresh方法中的registerBeanPostProcessors(beanFactory)方法(在上一篇文章里面——笔记8中):
/** Spring中大部分功能都是通过后处理的方式进行扩展的, 但是BeanFactory中其实并没有实现后处理的自动注册, 所以在调用的时候如果没有进行手动注册是不能使用的, 但是ApplicationContext中添加了自动注册功能。 **/ //举例:自定义一个后处理器。 class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor{ @Override public Object postProcessBeforeInstantiation(Class<?> aClass, String s) throws BeansException { System.out.println("################"); return null; } @Override public boolean postProcessAfterInstantiation(Object o, String s) throws BeansException { return false; } @Override public PropertyValues postProcessPropertyValues(PropertyValues propertyValues, PropertyDescriptor[] propertyDescriptors, Object o, String s) throws BeansException { return null; } @Override public Object postProcessBeforeInitialization(Object o, String s) throws BeansException { return null; } @Override public Object postProcessAfterInitialization(Object o, String s) throws BeansException { return null; } } //在配置中加上这句话: <bean class="test.MyInstantiationAwareBeanPostProcessor"/> /** 使用BeanFactory方式加载时不会有任何改变的,但是使用ApplicationContext方式获取bean时, 会在获取每个bean时打印出"################", 这个特性就是在registerBeanPostProcessors方法中完成的。 **/
//registerBeanPostProcessors源码: public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // Register BeanPostProcessorChecker that logs an info message when // a bean is created during BeanPostProcessor instantiation, i.e. when // a bean is not eligible for getting processed by all BeanPostProcessors. int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // Separate between BeanPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); List<String> nonOrderedPostProcessorNames = new ArrayList<>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, register the BeanPostProcessors that implement PriorityOrdered. sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement Ordered. List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } sortPostProcessors(orderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // Now, register all regular BeanPostProcessors. List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // Finally, re-register all internal BeanPostProcessors. sortPostProcessors(internalPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, internalPostProcessors); // Re-register post-processor for detecting inner beans as ApplicationListeners, // moving it to the end of the processor chain (for picking up proxies etc). beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
相关文章推荐
- Spring源码解析笔记8——容器的功能扩展ApplicationContext
- 【Spring学习24】容器扩展点:后置处理器BeanFactoryPostProcessor
- spring ioc容器的学习笔记4---XmlBeanFactory ioc容器的简单设计原理解析
- Spring源码解析-容器功能扩展
- Spring 源码梳理(四) BeanFactoryPostProcessor
- Spring源码分析之BeanPostProcessor接口和BeanFactoryPostProcessor接口方法不执行原因分析
- 003-Spring4 扩展分析BeanPostProcessor、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
- Spring BeanFactoryPostProcessor容器后处理器执行时机
- spring 容器后处理器 BeanFactoryPostProcessor 使用需要注意的一个问题
- 容器扩展点2 BeanFactoryPostProcessor自定义元数据配置
- Spring源码解析-AutowiredAnnotationBeanPostProcessor
- Spring源码分析之BeanPostProcessor接口和BeanFactoryPostProcessor接口方法不执行原因分析
- Ioc容器BeanPostProcessor-Spring 源码(3)
- Spring源码学习--BeanFactoryPostProcessor
- 【Spring学习23】容器扩展点:后置处理器BeanPostProcessor
- 做一个合格的程序猿之浅析Spring IoC源码(六)BeanFactoryPostProcessor
- spring开发_BeanFactoryPostProcessor_容器后处理器
- Spring学习08--IoC容器的高级特性(lazy-init、FactoryBean、BeanPostProcessor、autowiring)
- 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
- BeanFactoryPostProcessor接口(容器后处理器)