zoukankan      html  css  js  c++  java
  • BeanFactoryPostProcessor

    1 使用

    示例:去除Spring容器中潜在的敏感词信息,例如bean定义中过滤"zxt"、"sb"等词。

    1.1 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="customBeanFactoryPost" class="com.test.CustomBeanFactoryPostProcessor">
            <property name="obs">
                <set>
                    <value>zxt</value>
                    <value>sb</value>
                </set>
            </property>
        </bean>
        <bean id="u1" class="com.test.UserPO" >
            <property name="userName" value="sb" />
            <property name="email" value="zxt@163.com" />
            <property name="address" ref="testAddr" />
        </bean>
        <bean id="testAddr" class="com.test.Address" >
            <property name="desc" value="testDesc" />
            <property name="detail" value="testDetail" />
        </bean>
    </beans>
    
    

    1.2 POJO:UserPo

    public class UserPO {
        private String userName;
        private String email;
        private Address address;
        // setter, getter
    }
    
    public class Address {
        private String desc;
        private String detail;
        // setter, getter
    }
    

    1.3 BeanFactoryPostProcessor

    public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
        private Set<String> obs;
        public CustomBeanFactoryPostProcessor() {
            obs = new HashSet<>();
        }
    
        /// 数据解析
        private StringValueResolver valueResolver = (strVal) -> {
            if (obsContainValue(strVal)) {
                return "******";
            }
            return strVal;
        };
    
        //将所有bean 的参数中含有 obs 集合中的值进行屏蔽
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    
    
            String[] beanNames = beanFactory.getBeanDefinitionNames();
            for (String beanName : beanNames) {
                BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
                BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
                visitor.visitBeanDefinition(bd);
            }
    
        }
        private boolean obsContainValue(String value) {
            String strValue = value.toLowerCase();
            return this.obs.contains(strValue);
        }
        public void setObs(Set<String> obs) {
            this.obs.clear();
            for (String ob : obs) {
                this.obs.add(ob.toLowerCase());
            }
        }
    }
    

    1.4 测试

    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("custom-post.xml");
        UserPO userPO = (UserPO) ac.getBean("u1");
        System.out.println(userPO);
    }
    

    2 源码分析

    2.1 简介

    BeanFactoryPostProcessor是在AbstractApplicationContext扩展中实现的。在Spring容器实例化Bean之前的操作,是一个容器级别的处理器。

    在Spring中使用的${userName}的引用变量就是通过BeanFactoryPostProcessor实现的,即PropertyPlaceholderConfigurer

    2.2 源码

    AbstractApplicationContext#refresh()方法中,会获取beanFactory的所有BeanFactoryPostProcessor并进行调用

    public void refresh() throws BeansException, IllegalStateException {
        // 执行BeanFactory中的所有BeanFactoryPostProcessor
        invokeBeanFactoryPostProcessors(beanFactory);
    }
    
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    	// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    	// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    	if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    	}
    }
    

    执行BeanFactoryPostProcessor委托给了PostProcessorRegistrationDelegate类来实现。
    对于BeanFactoryPostProcessor的处理分为2种情况:

    • 特殊的BeanDefinitionRegistryPostProcessor
    • 常规的BeanFactoryPostProcessor

    无论是哪种情况,都需要考虑两种情况:

    • 硬编码注册后置处理器

      硬编码注册的后处理器主要通过:AbstractApplicationContext#addBeanFactoryPostProcessor()

    • 通过配置注入的后置处理器
    public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
    	Set<String> processedBeans = new HashSet<String>();
    	if (beanFactory instanceof BeanDefinitionRegistry) {
    		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    		// 记录通过硬编码方式注册的BeanFactoryPostProcessor
    		List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
    		// 记录通过硬编码方式注册的BeanDefinitionRegistryPostProcessor
    		List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
    		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
    			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
    				BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
    				registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
    				registryPostProcessors.add(registryPostProcessor);
    			} else {
    				regularPostProcessors.add(postProcessor);
    			}
    		}
    		// 获取所有通过配置文件注入的BeanDefinitionRegistryPostProcessor类
    		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    		
    		// 1.执行实现PriorityOrdered的所有BeanDefinitionRegistryPostProcessor
    		List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
    		for (String ppName : postProcessorNames) {
    			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    				processedBeans.add(ppName);
    			}
    		}
    		sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
    		registryPostProcessors.addAll(priorityOrderedPostProcessors);
    		invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
            // 2.执行实现Ordered的所有BeanDefinitionRegistryPostProcessor
    		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    		List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
    		for (String ppName : postProcessorNames) {
    			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
    				orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    				processedBeans.add(ppName);
    			}
    		}
    		sortPostProcessors(beanFactory, orderedPostProcessors);
    		registryPostProcessors.addAll(orderedPostProcessors);
    		invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
            // 3.执行其他所有的BeanDefinitionRegistryPostProcessor
    		boolean reiterate = true;
    		while (reiterate) {
    			reiterate = false;
    			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    			for (String ppName : postProcessorNames) {
    				if (!processedBeans.contains(ppName)) {
    					BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
    					registryPostProcessors.add(pp);
    					processedBeans.add(ppName);
    					pp.postProcessBeanDefinitionRegistry(registry);
    					reiterate = true;
    				}
    			}
    		}
    		invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
    		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    	} else {
    		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    	}
    
        // 获取所有配置注入的BeanFactoryPostProcessor,并执行
    	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    	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 (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);
    		}
    	}
    	sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
    	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    	for (String postProcessorName : orderedPostProcessorNames) {
    		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    	}
    	sortPostProcessors(beanFactory, orderedPostProcessors);
    	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    	for (String postProcessorName : nonOrderedPostProcessorNames) {
    		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    	}
    	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    
    	beanFactory.clearMetadataCache();
    }
    
  • 相关阅读:
    Linux下环境变量配置方法梳理(.bash_profile和.bashrc的区别)
    Mac下安装配置Python2和Python3并相互切换使用
    精通Python自动化脚本
    idea之Git
    python面向对象之:细分类的组成成员
    new string("abc")创建了几个对象
    进程和线程的主要区别
    Leetcode 572 另一个树的子树
    Leetcode 二叉树的坡度
    Leetcode 559 N叉树的最大深度
  • 原文地址:https://www.cnblogs.com/wolfdriver/p/10573395.html
Copyright © 2011-2022 走看看