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

简介: 结束了前面的基础结构分析,了解到 Spring 是如何识别配置文件和进行解析属性,最终将 bean 加载到内存中。同时为了更好得理解 Spring 的扩展功能,我们先来巩固一下 beanFactory 和 bean 的概念,然后再分析新内容后处理器 PostProcessor 。

流程图

11.jpg

代码

  1. public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
  2.    Set<String> processedBeans = new HashSet<>();
  3.    // beanFactory 默认使用的是 DefaultListableBeanFactory,属于 BeanDefinitionRegistry
  4.    if (beanFactory instanceof BeanDefinitionRegistry) {
  5.        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
  6.        // 两个后处理器列表
  7.        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
  8.        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
  9.        // 硬编码注册的后处理器
  10.        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
  11.            // 分类处理
  12.        }
  13.        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
  14.        // 首先,调用实现 priorityOrder 的 beanDefinition 这就是前面提到过的优先级概念,这一步跟下面的优先级不一样之处,这一步的优先级是带有权重
  15.        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
  16.        for (String ppName : postProcessorNames) {
  17.            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
  18.                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
  19.                processedBeans.add(ppName);
  20.            }
  21.        }
  22.        // 对后处理器进行排序
  23.        sortPostProcessors(currentRegistryProcessors, beanFactory);
  24.        registryProcessors.addAll(currentRegistryProcessors);
  25.        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
  26.        currentRegistryProcessors.clear();
  27.        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
  28.        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
  29.        for (String ppName : postProcessorNames) {
  30.            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
  31.                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
  32.                processedBeans.add(ppName);
  33.            }
  34.        }
  35.        sortPostProcessors(currentRegistryProcessors, beanFactory);
  36.        registryProcessors.addAll(currentRegistryProcessors);
  37.        // 执行 definitionRegistryPostProcessor 接口的方法 :postProcessBeanDefinitionRegistry
  38.        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
  39.        currentRegistryProcessors.clear();
  40.        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.最后,调用所有其他后处理器,直到不再出现其他 bean 为止
  41.        boolean reiterate = true;
  42.        while (reiterate) {
  43.            reiterate = false;
  44.            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
  45.            for (String ppName : postProcessorNames) {
  46.                if (!processedBeans.contains(ppName)) {
  47.                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
  48.                    processedBeans.add(ppName);
  49.                    reiterate = true;
  50.                }
  51.            }
  52.            sortPostProcessors(currentRegistryProcessors, beanFactory);
  53.            registryProcessors.addAll(currentRegistryProcessors);
  54.            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
  55.            currentRegistryProcessors.clear();
  56.        }
  57.        // 执行 postProcessBeanFactory 回调方法
  58.        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
  59.        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
  60.    }
  61.    else {
  62.        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
  63.    }
  64.    // 不要在这里初始化 factoryBean:我们需要保留所有常规 bean 未初始化,以便让 bean 工厂后处理程序应用于它们
  65.    // 注释 6.4 在这个步骤中,我们自定义的 carBeanFactoryPostProcessor 才真正注册并执行
  66.    String[] postProcessorNames =
  67.            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);.
  68.    // 跳过分类的逻辑
  69.    // 首先执行的是带有权重顺序的后处理器
  70.    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
  71.    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
  72.    // 下一步执行普通顺序的后处理器
  73.    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
  74.    for (String postProcessorName : orderedPostProcessorNames) {
  75.        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
  76.    }
  77.    sortPostProcessors(orderedPostProcessors, beanFactory);
  78.    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
  79.    // 最后执行的是普通的后处理器
  80.    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
  81.    for (String postProcessorName : nonOrderedPostProcessorNames) {
  82.        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
  83.    }
  84.    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
  85.    // 清除缓存的合并bean定义,因为后处理程序可能已经修改了原始元数据,例如替换值中的占位符
  86.    beanFactory.clearMetadataCache();
  87. }

从上面贴的代码中能够看到,对于 beanFactoryPostProcessor 的处理主要分两种情况:

  • beanFactoryBeanDefinitionRegistry 类型:需要特殊处理
  • beanFactory 不是 BeanDefinitionRegistry 类型:进行普通处理

对于每种情况都需要考虑硬编码注入注册的后处理器(上面已经提到如何进行硬编码)以及通过配置注入的后处理器

对于 BeanDefinitionRegistry 类型的处理器的处理主要包括以下内容:

  1. 处理硬编码注册的后处理器
  2. 记录后处理器主要使用以下三个 List
  • registryPostProcessors:记录通过硬编码方式注册的 BeanDefinitionRegistryPostProcessor
  • regularPostProcessors:记录通过硬编码方式注册的 BeanFactoryPostProcessor
  • regitstryPostProcessorBeans:记录通过配置方式注册的 BeanDefinitionRegistryPostProcessor
  1. 对于以上后处理器列表,统一调用 BeanFactoryPostProcessorpostProcessBeanFactory 方法
  2. beanFactoryPostProcessors 中非 BeanDefinitionRegistryPostProcessor 类型的后处理器进行统一的 postProcessBeanFactory 方法
  3. 普通 beanFactory 处理:其实在这一步中,就是忽略了 BeanDefinitionRegistryPostProcessor 类型,对BeanFactoryPostProcessor 进行直接处理。

流程图中描述了整体调用链路,具体调用方法在代码中的注释也描述出来了,所以结合起来看应该能够理解整体流程~


总结

本次分析了 beanFactory 的后处理器 BeanFactoryPostProcessor,了解了 Spring 给我们提供的这个扩展接口使用用途和在源码中如何进行激活执行。


由于个人技术有限,如果有理解不到位或者错误的地方,请留下评论,我会根据朋友们的建议进行修正

代码和注释都在里面,小伙伴们可以下载我上传的代码,亲测可运行~

Gitee 地址:https://gitee.com/vip-augus/spring-analysis-note.git

Github 地址:https://github.com/Vip-Augus/spring-analysis-note


参考资料

  1. Bean 定义
  2. Sping 的 BeanFactory 容器
  3. Spring拓展接口之BeanFactoryPostProcessor,占位符与敏感信息解密原理
相关文章
|
1月前
|
搜索推荐 JavaScript Java
基于springboot的儿童家长教育能力提升学习系统
本系统聚焦儿童家长教育能力提升,针对家庭教育中理念混乱、时间不足、个性化服务缺失等问题,构建科学、系统、个性化的在线学习平台。融合Spring Boot、Vue等先进技术,整合优质教育资源,提供高效便捷的学习路径,助力家长掌握科学育儿方法,促进儿童全面健康发展,推动家庭和谐与社会进步。
|
1月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
354 2
|
3月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
6月前
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
238 32
|
5月前
|
安全 Java 数据库
Spring Boot 框架深入学习示例教程详解
本教程深入讲解Spring Boot框架,先介绍其基础概念与优势,如自动配置、独立运行等。通过搭建项目、配置数据库等步骤展示技术方案,并结合RESTful API开发实例帮助学习。内容涵盖环境搭建、核心组件应用(Spring MVC、Spring Data JPA、Spring Security)及示例项目——在线书店系统,助你掌握Spring Boot开发全流程。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
815 2
|
6月前
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
|
7月前
|
Java Spring
Spring框架的学习与应用
总的来说,Spring框架是Java开发中的一把强大的工具。通过理解其核心概念,通过实践来学习和掌握,你可以充分利用Spring框架的强大功能,提高你的开发效率和代码质量。
191 20
|
5月前
|
监控 安全 Java
Java 开发中基于 Spring Boot 3.2 框架集成 MQTT 5.0 协议实现消息推送与订阅功能的技术方案解析
本文介绍基于Spring Boot 3.2集成MQTT 5.0的消息推送与订阅技术方案,涵盖核心技术栈选型(Spring Boot、Eclipse Paho、HiveMQ)、项目搭建与配置、消息发布与订阅服务实现,以及在智能家居控制系统中的应用实例。同时,详细探讨了安全增强(TLS/SSL)、性能优化(异步处理与背压控制)、测试监控及生产环境部署方案,为构建高可用、高性能的消息通信系统提供全面指导。附资源下载链接:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)。
934 0

热门文章

最新文章