文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何在Spring中实现一个BeanFactoryPostProcessor接口

2023-06-06 12:59

关注

本篇文章为大家展示了如何在Spring中实现一个BeanFactoryPostProcessor接口,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

接口简介

BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。

BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。

如何在Spring中实现一个BeanFactoryPostProcessor接口

注意点:通过BeanDefinitionRegistryPostProcessor 注册的 BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry方法将得不到调用,具体的原因会在下面的代码中解释。

BeanFactoryPostProcessor 接口调用机制

BeanFactoryPostProcessor 接口的调用在 AbstractApplicationContext#invokeBeanFactoryPostProcessors方法中。

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()));}}

进入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法:

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {   // 用于存放已经处理过的Bean名字Set<String> processedBeans = new HashSet<>();   // 一般会进入这个判断if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;    // 所谓的regularPostProcessors就是指实现BeanFactoryPostProcessor接口的BeanList<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();    // 所谓的registryProcessors就是指实现BeanDefinitionRegistryPostProcessor接口的BeanList<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();    // 这边遍历的是通过ApplicationContext接口注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口    // 需要和BeanFactory中BeanDefinitionMap中的BeanFactoryPostProcessor接口区分开for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {BeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;      //如果是BeanDefinitionRegistryPostProcessor,则先进行postProcessBeanDefinitionRegistry处理,这个方法一般进行BeanDefinition注册,从这边可以看出BeanDefinitionRegistryPostProcessor接口的方法先调用,所以优先级高于BeanFactoryPostProcessor      // 通过这个代码可以看出,通过ApplicationContext直接注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor并不支持Order接口,而是根据注册的顺序执行registryProcessor.postProcessBeanDefinitionRegistry(registry);      // 保存这个BeanDefinitionRegistryPostProcessor,因为还要执行这个类的BeanFactoryPostProcessor方法;registryProcessors.add(registryProcessor);}else {      // 保存,后面还要执行这个类的BeanFactoryPostProcessor方法;regularPostProcessors.add(postProcessor);}}List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();    // 这边获取的是BeanFactory中的BeanDefinitionRegistryPostProcessorString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {     //先处理PriorityOrdered标注的BeanDefinitionRegistryPostProcessorif (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));      //将其标记为已经处理,防止重复处理processedBeans.add(ppName);}}    // 将其排序,以便按顺序处理sortPostProcessors(currentRegistryProcessors, beanFactory);    // 将其保存,以便处理这个类的BeanFactoryPostProcessor方法registryProcessors.addAll(currentRegistryProcessors);    // 执行BeanDefinitionRegistryPostProcessor接口方法invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);    // 清除,以便开始处理@Order标注的注解currentRegistryProcessors.clear();      // 注意:这边重新获取BeanDefinitionRegistryPostProcessor是有深意的,因为上面在处理@PriorityOrdered标注的BeanDefinitionRegistryPostProcessor时可能又注入了新的BeanDefinitionRegistryPostProcessor。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();    // 处理不标注注解的BeanDefinitionRegistryPostProcessorboolean 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();}// 调用postProcessBeanFactory 方法,所以BeanDefinitionRegistryPostProcessor中的postProcessBeanFactory方法的优先级要高。invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {// Invoke factory processors registered with the context instance.invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}// 开始处理BeanFactoryPostProcessor接口String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);// 也是按照@PriorityOrdered @Ordered 和普通的方式进行处理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);}}   // 先执行@PriorityOrdered标注的接口sortPostProcessors(priorityOrderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);   // 处理@Order标注的类List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());for (String postProcessorName : orderedPostProcessorNames) {    // 这边通过名字重新拿了Bean,应该是怕上面的处理改变了BeanorderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));}sortPostProcessors(orderedPostProcessors, beanFactory);invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// 最后调用普通的BeanFactoryPostProcessorList<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());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();}

简单总结

上面的方法看起来很长很复杂,但其实干的事情并不多,就调用了BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口的实现。这边再简单总结下具体的过程:

step1:执行通过ApplicationContext#addBeanFactoryPostProcessor()方法注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。

具体过程如下:假如通过ApplicationContext注册了一个BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,那么会先执行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,但是BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法和BeanFactoryPostProcessor的postProcessBeanFactory方法暂时都不会在这步执行。

另外需要注意的是:通过ApplicationContext注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都不支持@PriorityOrdered和@Ordered顺序处理,而是按照我们添加的顺序处理

step2:处理BeanFactory中的BeanDefinitionRegistryPostProcessor,处理的顺序是先处理@PriorityOrdered标注的,再处理@Ordered标注的,最后处理普通的BeanDefinitionRegistryPostProcessor。到这边,所有BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法都已经调用完毕,下面就开始处理BeanFactoryPostProcessor的postProcessBeanFactory方法。

step3:调用BeanDefinitionRegistryPostProcessor实现的postProcessBeanFactory方法(因为BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口)

step4:调用通过ApplicationContext#addBeanFactoryPostProcessor()注册的“单纯”的BeanFactoryPostProcessor

step5:调用BeanFactory中的BeanFactoryPostProcessor,调用顺序也是按照@PriorityOrdered和@Ordered顺序处理,没有这两个注解的最后处理。

好了,到这边BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口就已经处理完了。后面我们会拿ConfigurationClassPostProcessor 这个特殊的BeanDefinitionRegistryPostProcessor做列子讲下具体流程,这边只是介绍BeanFactoryPostProcessor的调用机制。

上述内容就是如何在Spring中实现一个BeanFactoryPostProcessor接口,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯