深度理解spring——BeanFactory的实现

BeanFactory

  • Spring之BeanFactory
    • 什么是BeanFactory
    • ApplicationContext相对BeanFactory实现的功能性扩展
      • 1. MessageSource
      • 2. ResourcePatternResolver
      • 3. ApplicationEventPublisher
      • 4. EnvironmentCapable
      • 通用ApplicationContext实践实现BeanFactory
      • BeanFactory后处理器排序让谁优先执行
      • 第一种实现通过xml等方式实现的bean注入原理
        • 第二种基于磁盘路径下 xml 格式的配置文件来创建
        • 第三种较为经典的容器,基于java配置类来创建
        • 第四种较为经典的容器,基于java配置类来创建,并且还可以用于web环境

Spring之BeanFactory

什么是BeanFactory

BeanFactory是SpringApplication类的父类接口
BeanFactory才是Spring的核心容器,主要的SpringApplication类都组合了他的功能。
通过Ctrl+alt+u可以看到
在这里插入图片描述
可以从图片中看到SpringApplication是继承了BeanFactory接口对BeanFactory进行了功能性的扩展。
比如SpringApplication获取一个bean的对象

       run.getBean(BreadRollMallServer.class);

他实际上是通过组合了BeanFactory实现找个获取对象的功能,可以看出来SpringApplication是间接的调用了BeanFactory的功能
在这里插入图片描述

ApplicationContext相对BeanFactory实现的功能性扩展

在这里插入图片描述

1. MessageSource

MessageSource 是 Spring 框架里用于消息解析与国际化的核心接口。借助它,你能够依据不同的语言环境获取对应的文本消息,从而实现国际化支持。像错误消息、提示信息这类文本内容,就可以通过 MessageSource 进行管理。

2. ResourcePatternResolver

ResourcePatternResolver 接口可用来解析资源路径,并且支持使用通配符来匹配多个资源。它是 ResourceLoader 的扩展,能够依据给定的资源路径模式查找多个资源。在加载配置文件、静态资源等场景中会经常用到。

3. ApplicationEventPublisher

ApplicationEventPublisher 接口提供了发布应用事件的功能。在 Spring 应用里,事件机制是一种重要的设计模式,允许组件之间以松耦合的方式进行通信。通过 ApplicationEventPublisher,你可以发布自定义的应用事件,其他组件可以监听这些事件并做出响应。

应用场景:用户注册时候的发短信发邮件。

4. EnvironmentCapable

EnvironmentCapable 接口表明一个对象具备获取 Environment 对象的能力。Environment 对象封装了应用程序运行时的环境信息,包含系统属性、环境变量、配置文件属性等。借助 Environment,你可以方便地获取和管理这些属性。

通用ApplicationContext实践实现BeanFactory

public class TestBeanFactory {public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();// bean 的定义(class(类型), scope(单例or多例), 初始化方法, 销毁方法)// BeanDefinitionBuilder..xxx.xxx.xxx.getBeanDefinition()AbstractBeanDefinition beanDefinition =BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();//(beanName,xxx)将bean注册到bean工厂中beanFactory.registerBeanDefinition("config", beanDefinition);// 【重点】给 BeanFactory 添加一些常用的后处理器(对BeanFactory的扩展) //将后处理添加到bean工厂AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);// BeanFactory 后处理器主要功能,补充了一些 bean 定义// beanFactory.getBeansOfType 根据类型获取多个bean//BeanFactoryPostProcessor.class拿到bean工厂的所有后处理器,对bean工厂做出扩展就可以解析@bean注解等。beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {//拿到bean工厂的所有后处理器并且执行beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);//执行BeanFactory后置处理器});// 添加 BeanPostProcessor  也就是添加bean的后处理器//bean后处理器 针对bean的生命周期各个阶段进行扩展,例如@Autowire @ResousebeanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);for (String name : beanFactory.getBeanDefinitionNames()) {System.out.println(name);}}@Configurationstatic class Config {@Beanpublic Bean1 bean1() {return new Bean1();}@Beanpublic Bean2 bean2() {return new Bean2();}}static class Bean1 {private static final Logger log = LoggerFactory.getLogger(Bean1.class);@Autowiredprivate Bean2 bean2;}static class Bean2 {private static final Logger log = LoggerFactory.getLogger(Bean2.class);}
}

通过这个案例,你可以看到如何使用 DefaultListableBeanFactory 创建和管理 Bean,以及如何使用后置处理器在 Bean 的生命周期中执行自定义逻辑。
区别对比

  1. 作用时机
    BeanFactoryPostProcessor:在 BeanFactory 完成 Bean 定义的加载之后,但在 Bean 实例化之前执行。也就是说,它处理的是 Bean 的定义信息,而不是 Bean 实例。
    BeanPostProcessor:在 Bean 实例化之后,初始化前后执行。它作用于已经创建好的 Bean 实例。
  2. 作用对象
    BeanFactoryPostProcessor:作用于 BeanFactory 本身,主要用于修改 BeanFactory 中 Bean 的定义信息,例如修改 Bean 的属性值、作用域等。
    BeanPostProcessor:作用于具体的 Bean 实例,允许开发者在 Bean 初始化前后对其进行定制化处理。
  3. 功能侧重点
    BeanFactoryPostProcessor:侧重于对 Bean 定义的全局修改和扩展,例如动态添加或修改 Bean 定义,调整 Bean 的配置等。
    BeanPostProcessor:侧重于对 Bean 实例的个性化处理,例如对 Bean 进行增强、验证、日志记录等。

总结:
1.bean工厂不会主动调用beanFactory后处理器
2.bean不会主动添加后处理器
3.不会主动初始化单例
4.不会解析BeanFactory

BeanFactory后处理器排序让谁优先执行

在这里插入图片描述

第一种实现通过xml等方式实现的bean注入原理

通过xml注入bean容器

  // ⬇️1.最为经典的容器,基于classpath 下 xml 格式的配置文件来创建public void testClassPathXmlApplicationContext() {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring_bean.xml");for (String name : context.getBeanDefinitionNames()) {System.out.println(name);}System.out.println(context.getBean(Bean2.class).getBean1());}
第二种基于磁盘路径下 xml 格式的配置文件来创建
        //基于磁盘路径下 xml 格式的配置文件来创建DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();System.out.println("读取之前");for (String name : beanFactory.getBeanDefinitionNames()) {System.out.println(name);}System.out.println("读取之后");XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);;reader.loadBeanDefinitions(new FileSystemResource("src\\main\\resources\\spring_bean.xml"));for (String name : beanFactory.getBeanDefinitionNames()) {System.out.println(name);}
第三种较为经典的容器,基于java配置类来创建

较为经典的容器,基于java配置类来创建,通过这个配置类创建会帮我们创建后处理器了来解析@Bean注解

   // ⬇️3.较为经典的容器,基于java配置类来创建public void testAnnotationConfigApplicationContext() {// 会自动加上5个后处理器// org.springframework.context.annotation.internalConfigurationAnnotationProcessor// org.springframework.context.annotation.internalAutowiredAnnotationProcessor// org.springframework.context.annotation.internalCommonAnnotationProcessor// org.springframework.context.event.internalEventListenerProcessor// org.springframework.context.event.internalEventListenerFactoryAnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);for (String name : context.getBeanDefinitionNames()) {System.out.println(name);}System.out.println(context.getBean(Bean2.class).getBean1());}
// 单元测试的过程中如果要解析一些Spring注解,比如@Configuration的时候不要把相关类定义到写单元测试类的内部类,会读取不到
@Configuration
class Config {@Beanpublic Bean1 bean1() {return new Bean1();}@Beanpublic Bean2 bean2(Bean1 bean1) {Bean2 bean2 = new Bean2();bean2.setBean1(bean1);return bean2;}
}class Bean1 {}class Bean2 {private Bean1 bean1;public Bean1 getBean1() {return bean1;}public void setBean1(Bean1 bean1) {this.bean1 = bean1;}
}
第四种较为经典的容器,基于java配置类来创建,并且还可以用于web环境
// 模拟了 springboot web项目内嵌Tomcat的工作原理public void testAnnotationConfigServletWebServerApplicationContext() throws IOException {AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext(WebConfig.class);// 防止程序终止System.in.read();}@Configuration
class WebConfig {@Bean// 1. WebServer工厂public ServletWebServerFactory servletWebServerFactory() {return new TomcatServletWebServerFactory();}@Bean// 2. web项目必备的DispatcherServletpublic DispatcherServlet dispatcherServlet() {return new DispatcherServlet();}@Bean// 3. 将DispatcherServlet注册到WebServer上public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {return new DispatcherServletRegistrationBean(dispatcherServlet, "/");}@Bean("/hello")public Controller controller1() {return (request, response) -> {response.getWriter().println("hello");return null;};}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/902727.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跑MPS产生委外采购申请(成品)

问题:跑MPS产生委外采购申请(成品),更改BOM和跑MRP,但物料需求清单中无新增物料复合膜的需求。截图如下: 解决方法:更改委外采购申请的批准日期为BOM的生效日和重新展开bom。 重新展开后&#x…

“在中国,为中国” 英飞凌汽车业务正式发布中国本土化战略

3月28日,以“夯实电动化,推进智能化,实现高质量发展”为主题的2025中国电动汽车百人会论坛在北京举办。众多中外机构与行业上下游嘉宾就全球及中国汽车电动化的发展现状、面临的挑战与机遇,以及在技术创新、市场布局、供应链协同等…

优雅实现网页弹窗提示功能:JavaScript与CSS完美结合

在现代Web开发中,弹窗提示是提升用户体验的重要元素之一。本文将深入探讨如何实现一个优雅、可复用的弹窗提示系统,避免常见问题如重复触发、样式混乱等。 核心代码解析 // 控制弹窗是否可以显示的标志 let alertStatus true;// 显示提示信息 functio…

YOLOv11改进-双Backbone架构:利用双backbone提高yolo11目标检测的精度

一、引言:为什么我们需要双Backbone? 在目标检测任务中,YOLO系列模型因其高效的端到端检测能力而备受青睐。然而,传统YOLO模型大多采用单一Backbone结构,即利用一个卷积神经网络(CNN)作为特征提…

用 PyQt5 和 asyncio 打造接口并发测试 GUI 工具

接口并发测试是测试工程师日常工作中的重要一环,而一个直观的 GUI 工具能有效提升工作效率和体验。本篇文章将带你用 PyQt5 和 asyncio 从零实现一个美观且功能实用的接口并发测试工具。 我们将实现以下功能: 请求方法选择器 添加了一个下拉框 QComboBo…

理解npm的工作原理:优化你的项目依赖管理流程

目录 什么是npm npm核心功能 npm 常用指令及其作用 执行npm i 发生了什么? 1. 解析命令与参数 2. 检查依赖文件 3. 依赖版本解析与树构建 4. 缓存检查与包下载 5. 解压包到 node_modules 6. 更新 package-lock.json 7. 处理特殊依赖类型 8. 执行生命周期脚本 9. …

React Native 安卓端 android Image 播放gif webp 动态图

React Native 安卓端 android Image 播放gif webp 动态图 RN项目是0.78.2 React是19.0 基本介绍 Image 是 React Native 中用于显示各种类型图片的核心组件,支持显示网络图片、静态资源、本地图片以及 base64 编码的图片。在 Android 端,Image 组件还可…

实时数字人——DH_LIVE

前两天亲手搭建了实时对话数字人VideoChat,今天来搭建下DH_LIVE。 DH_LIVE一个实时数字人解决方案,从输入文字到数字人对口型说话用时2-3秒。 今天就来实际操作下dh_live的搭建过程。 首先贴上git地址:https://github.com/kleinlee/DH_liv…

AOSP CachedAppOptimizer 冻结方案

背景 Android 一直面临一个核心难题:如何优化进程对有限系统资源(如 CPU、电量)的使用,同时保证用户体验。 当进程进入后台后,它们虽不再贡献用户体验,却仍可能消耗资源。传统的杀后台方案虽然节省资源&a…

实体店的小程序转型之路:拥抱新零售的密码-中小企实战运营和营销工作室博客

实体店的小程序转型之路:拥抱新零售的密码-中小企实战运营和营销工作室博客 在当今数字化浪潮的冲击下,实体店面临着前所未有的挑战,但小程序的出现为实体店转型新零售带来了新的曙光。先来看一组惊人的数据,据相关统计&#xff…

Java求职面试:从Spring Boot到微服务的全面考核

Java求职面试实录:从Spring Boot到微服务的全面考核 第一轮:基础技术的考察 场景: 赵大宝走进了一家互联网大厂的面试间,面试官严肃地看着他。 面试官: 赵大宝,你好。我们先从简单的开始。请你解释一下J…

记录一个坑关于STM32 ARM Compiler Version

在用 Keil 进行 STM32 开发的时候,一开始下载,下载的 ARM 编译器是 Version6,他就不兼容老的代码,就很抽象。 所以必须要更换编译器。 可以去官网下载编译器 Downloads - Arm Developer ,也可以自己找资源哈&#xff…

PCIe体系结构学习入门——PCI总线概述(二)PCI总线的桥和配置

这里写目录标题 序言存储器域和 PCI 总线域HOST 主桥PCI 桥和 PCI 设备配置空间PCI 桥PCI 设备配置空间PCI 总线的配置非透明 PCI 桥序言 接续前章内容,本章继续讲述 PCI 总线概述的第二部分——PCI 总线的桥和配置。 如果需要进一步了解前一章节内容,可以访问:PCIe体系结构…

浔川代码编辑器v2.0(测试版)更新公告

浔川代码编辑器v2.0(测试版)更新公告 发布日期:** 2023年4月30日 我们很高兴地宣布浔川代码编辑器v2.0测试版即将上线!本次更新带来了多项功能改进和问题修复,旨在为用户提供更稳定、更强大的编程体验。 主要更新内容 1. **Bug修复与稳定性提…

微信小程序 tabbar底部导航栏

官方文档:https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#tabBar 一、常规菜单格式 在app.json 文件中配置,其他关键点详见官方文档,后续更新不规则图标的写法

Spring 中@Autowired,@Resource,@Inject 注解实现原理

使用案例 前置条件: 现在有一个 Vehicle 接口,它有两个实现类 Bus 和 Car ,现在还有一个类 VehicleService 需要注入一个 Vehicle 类型的 Bean: public interface Vehicle {}Component public class Car implements Vehicle {}C…

【Rust结构体】Rust结构体详解:从基础到高级应用

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

《LightLLM:开启大语言模型推理新时代》

《LightLLM:开启大语言模型推理新时代》 大语言模型推理的困境与挑战 在当今人工智能飞速发展的时代,大语言模型(LLMs)无疑是最为耀眼的明星技术之一。从 OpenAI 的 GPT 系列到谷歌的 BERT,再到国内如百度文心一言、阿里通义千问等,大语言模型以其强大的语言理解和生成能…

【Python Web开发】02-Socket网络编程02

文章目录 1. 服务器端1.1 socket.socket()1.2 socket.bind()1.3 socket.listen()1.4 socket.accept()1.5 socket.recv()1.6 socket.send() 和 socket.sendall()1.7 socket.close() 2. 客户端2.1 socket.socket()2.2 socket.connect()2.3 socket.send() 和 socket.sendall()2.4 …

Flutter 在全新 Platform 和 UI 线程合并后,出现了什么大坑和变化?

Flutter 在全新 Platform 和 UI 线程合并后,出现了什么大坑和变化? 在两个月前,我们就聊过 3.29 上《Platform 和 UI 线程合并》的具体原因和实现方式,而事实上 Platform 和 UI 线程合并,确实为后续原生语言和 Dart 的…