六 Spring 源码学习扩展功能 上篇( 二 )


所以通过后处理器 , 我们能够对中的 bean 配置信息在实例化前还有机会进行修改 。
题外话:想到之前我遇到全半角空格的配置问题 , 程序认为全半角空格不是同一个字符 , 但肉眼却很难察觉 , 所以感觉可以在加载配置信息时 , 通过自定义一个后处理 , 在实例化之前 , 将全角空格转成半角空格 , 这样程序比较时都变成统一样式 。所以后处理器提供的扩展功能可以让我们对想要处理的 bean 配置信息进行特定修改
使用自定义 ssor
实现的功能与书中的类似 , 例如之前西安奔驰汽车维权事件 , 如果相关网站想要屏蔽这奔驰这两个字 , 可以通过后处理器进行替换:
1. 配置文件 -post-.xml
奔驰 特斯拉
2. 后处理器
public class CarBeanFactoryPostProcessor implements BeanFactoryPostProcessor { /** * 敏感词 */ private Set obscenties; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 从 beanFactory 中获取 bean 名字列表 String[] beanNames = beanFactory.getBeanDefinitionNames(); for (String beanName : beanNames) { BeanDefinition definition = beanFactory.getBeanDefinition(beanName); StringValueResolver valueResolver = strVal -> { if (isObscene(strVal)) return "*****"; return strVal; }; BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver); // 这一步才是真正处理 bean 的配置信息 visitor.visitBeanDefinition(definition); } } /** * 判断 value 是否在敏感词列表中 * @param value 值 * @returnboolean */ private boolean isObscene(Object value) { String potentialObscenity = value.toString().toUpperCase(); return this.obscenties.contains(potentialObscenity); } }
3. 启动
public class BeanFactoryPostProcessorBootstrap { public static void main(String[] args) { ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("factory.bean/factory-post-processor.xml"); // 这两行其实可以不写 , 因为在 refresh() 方法中 , 调用了一个函数将后处理器执行了 , 具体请往下看~ BeanFactoryPostProcessor beanFactoryPostProcessor = (BeanFactoryPostProcessor) context.getBean("carPostProcessor"); beanFactoryPostProcessor.postProcessBeanFactory(context.getBeanFactory()); // 输出 :Car{maxSpeed=0, brand='*****', price=10000.0} , 敏感词被替换了 System.out.println(context.getBean("car")); } }
通过上面的演示代码 , 新增一个自定义实现 ssor 的后处理器  , 在 ry 方法中进行逻辑处理 , 最后通过 . 修改配置信息 。
【六Spring 源码学习扩展功能 上篇】查看输出结果 , 能发现宝马敏感词已经被屏蔽了 , 实现了后处理器的逻辑功能~
在哪注册
按照一般套路 , 后处理器需要有个地方进行注册 , 然后才能进行执行 , 通过代码分析 , 的确在中看到了 ssors 数组列表 , 但往数组中添加后处理器的方法只在单元测试包调用了 。
这让我很迷惑它到底是在哪里进行注册 , 直到我看到它的执行方法 , 原来我们定义的后处理器在 bean 信息加载时就放入注册表中 , 然后通过 .(.class,true,false) 方法获取后处理器列表遍历执行 。