Spring Framework源码解析——BeanFactory


版权声明

  • 本文原创作者:谷哥的小弟
  • 作者博客地址:http://blog.csdn.net/lfdfhl

在这里插入图片描述

1. BeanFactory 概述

BeanFactory 是 Spring IoC 容器的最基础接口,它定义了获取、配置和管理 Bean 的核心方法。它是 Spring 框架中容器体系的顶层接口之一,提供了最基本的依赖注入功能。

1.1 接口定义

public interface BeanFactory {String FACTORY_BEAN_PREFIX = "&";Object getBean(String name) throws BeansException;<T> T getBean(String name, Class<T> requiredType) throws BeansException;<T> T getBean(Class<T> requiredType) throws BeansException;boolean containsBean(String name);boolean isSingleton(String name) throws BeansException;boolean isPrototype(String name) throws BeansException;boolean isTypeMatch(String name, ResolvableType typeToMatch) throws BeansException;Class<?> getType(String name) throws BeansException;String[] getAliases(String name);
}
  • getBean:获取容器中已注册的 Bean 实例。
  • containsBean:判断某个名称的 Bean 是否存在。
  • isSingleton / isPrototype:判断 Bean 的作用域。
  • getType / isTypeMatch:获取或匹配 Bean 的类型。
  • getAliases:获取某个 Bean 的所有别名。

1.2 与 ApplicationContext 的关系

  • BeanFactory 是 Spring 容器的基础接口。
  • ApplicationContext 是其子接口,扩展了 BeanFactory 的功能,增加了国际化、事件发布、资源加载等高级功能。
  • BeanFactory 是“按需加载”,而 ApplicationContext 是“预加载单例 Bean”。

2. 核心实现类

DefaultListableBeanFactory 是 Spring 中最常用的 BeanFactory 实现类,它实现了 BeanDefinitionRegistry 接口,支持注册和管理 Bean 定义。

2.1. 核心属性

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry {private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
}
  • beanDefinitionMap:存储 Bean 名称与 BeanDefinition 的映射关系。
  • beanDefinitionNames:存储所有已注册的 Bean 名称列表。

2.2 注册 Bean 定义

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {this.beanDefinitionMap.put(beanName, beanDefinition);if (!this.beanDefinitionNames.contains(beanName)) {this.beanDefinitionNames.add(beanName);}
}
  • 将 Bean 定义放入 beanDefinitionMap 中。
  • 将 Bean 名称加入 beanDefinitionNames 列表。

3. Bean 的加载过程

getBean() 是获取 Bean 的核心方法。其调用链如下:

getBean()doGetBean()getSingleton()createBean()doCreateBean()populateBean()initializeBean()

3.1 doGetBean() 方法

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {final String beanName = transformedBeanName(name);Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {// 如果是 FactoryBean,处理 & 前缀bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);} else {// 创建 Beanbean = createBean(beanName, mbd, args);}return (T) bean;
}
  • transformedBeanName:处理 & 前缀(用于获取 FactoryBean 本身)。
  • getSingleton:尝试从单例缓存中获取 Bean。
  • createBean:如果不存在,调用 createBean 创建新实例。

3.2 单例 Bean 的创建

3.2.1 getSingleton() 方法

public Object getSingleton(String beanName) {return this.singletonObjects.get(beanName);
}
  • singletonObjects:是一个 Map<String, Object>,缓存所有已创建的单例 Bean。

3.2.2 创建 Bean 的流程

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// 1. 解析 Bean 的 ClassClass<?> resolvedClass = resolveBeanClass(mbd, beanName);// 2. 实例化 BeanObject beanInstance = instantiateBean(beanName, mbd);// 3. 属性注入populateBean(beanName, mbd, instanceWrapper);// 4. 初始化 BeanexposedObject = initializeBean(beanName, exposedObject, mbd);// 5. 注册为单例addSingleton(beanName, exposedObject);return exposedObject;
}

4. Bean 的生命周期

Spring 中 Bean 的生命周期由 BeanFactory 管理,其流程如下:

  1. 实例化:通过构造方法或工厂方法创建 Bean 实例。
  2. 属性注入:注入依赖的其他 Bean 或配置值。
  3. 初始化前回调:如 BeanNameAwareBeanFactoryAware 等接口的回调。
  4. 初始化方法调用:如 @PostConstructInitializingBean 接口或配置的 init-method
  5. 使用 Bean:Bean 可以被使用。
  6. 销毁前回调:如 @PreDestroyDisposableBean 接口或配置的 destroy-method
  7. 销毁 Bean:清理资源。

初始化 Bean 示例如下:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {// 调用 Aware 接口方法invokeAwareMethods(beanName, bean);// 调用初始化方法if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}invokeInitMethods(beanName, wrappedBean, mbd);if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}

5. 工厂 Bean(FactoryBean)

FactoryBean 是一种特殊的 Bean,它本身是一个工厂,用于创建其他 Bean。

5.1 接口定义

public interface FactoryBean<T> {T getObject() throws Exception;Class<?> getObjectType();boolean isSingleton();
}

5.2 获取 FactoryBean 实例

Object bean = getBean("&myFactoryBean");
assertTrue(bean instanceof FactoryBean);
  • 使用 & 前缀获取 FactoryBean 本身。
  • 不带前缀则获取其 getObject() 返回的 Bean。

6. Bean 的作用域(Scope)

Spring 支持多种作用域,包括:

  • singleton(默认):每个容器中只有一个实例。
  • prototype:每次调用 getBean() 都返回一个新实例。
  • request / session(Web 作用域):每个请求或会话一个实例。

作用域实现机制如下:

public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {String beanName = transformedBeanName(name);RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);return mbd.isSingleton();
}
  • RootBeanDefinition 中保存了 Bean 的作用域配置。

7. BeanFactory 的扩展机制

7.1 BeanFactoryPostProcessor

允许在 Bean 实例化之前修改 BeanDefinition

public interface BeanFactoryPostProcessor {void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

示例:

public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {BeanDefinition beanDef = beanFactory.getBeanDefinition("myBean");beanDef.setScope(BeanDefinition.SCOPE_PROTOTYPE);}
}

7.2 BeanPostProcessor

允许在 Bean 实例化前后进行干预。

public interface BeanPostProcessor {default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}

8. BeanFactory 与 ApplicationContext 的对比

特性BeanFactoryApplicationContext
初始化时机按需加载(懒加载)启动时预加载单例 Bean
功能特性仅提供基本的依赖注入提供国际化、事件发布、资源加载等高级功能
资源加载仅支持类路径加载支持多种资源加载方式(如 Ant 路径)
扩展点支持需手动注册 BeanPostProcessor 等组件自动注册并调用扩展点

9. 核心代码示例与解释

9.1 手动注册 Bean 定义并获取 Bean

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
RootBeanDefinition definition = new RootBeanDefinition(MyBean.class);
factory.registerBeanDefinition("myBean", definition);MyBean bean = factory.getBean("myBean", MyBean.class);
System.out.println(bean);
  • 创建 DefaultListableBeanFactory
  • 定义 BeanDefinition
  • 注册 Bean 定义。
  • 获取 Bean 实例。

9.2 使用 BeanFactoryPostProcessor 修改 Bean 定义

factory.addBeanPostProcessor(new CustomBeanFactoryPostProcessor());
  • 将自定义的 BeanFactoryPostProcessor 添加到容器中。

10. 总结

BeanFactory 是 Spring IoC 容器的核心接口之一,它提供了最基本的依赖注入功能。其设计体现了模块化、可扩展性和灵活性,是构建 Spring 容器体系的基础。通过理解其源码结构、生命周期管理、Bean 加载机制以及扩展机制,开发者可以更深入地掌握 Spring 的运行原理,并在实际项目中更好地进行配置和优化。实践建议如下:

  1. 优先使用 ApplicationContext:在企业级应用中推荐使用,因其提供了更全面的功能。
  2. 理解 BeanFactory 的懒加载机制:适用于资源受限的场景。
  3. 合理使用 BeanPostProcessorBeanFactoryPostProcessor:用于扩展容器行为。
  4. 避免过度依赖 BeanFactory 的底层 API:保持代码的可测试性和可维护性。

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

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

相关文章

C# 计算梯形面积和周长的程序(Program to calculate area and perimeter of Trapezium)

梯形是至少有一对边平行&#xff0c;其他两条边可以不平行的四边形。平行边称为梯形的底&#xff0c;其他两条边称为梯形的腿。平行边之间的垂直距离称为梯形的高。公式 &#xff1a; 梯形面积&#xff1a; 0.5 * (a b) * h梯形周长&#xff1a; a b c d例子&#xff1a; 输…

【计算机考研(408)- 数据结构】数组和特殊矩阵

数组和特殊矩阵 数组 数组的定义 数组是由n(n>1)个相同类型的数据元素构成的有限序列。每个数据元素称为一个数组元素&#xff0c;每个元素在n个线性关系中的序号称之为该元素的下标&#xff0c;下标的取值范围称为数组的维界。 数组是[[线性表]]的推广&#xff0c;一维数组…

Agent架构与工作原理:理解智能体的核心机制

Agent架构与工作原理&#xff1a;深入理解智能体的核心机制 AI Agent的核心组成部分 一个完整的AI Agent通常由以下几个核心模块组成&#xff1a; 1. 规划模块&#xff08;Planning Module&#xff09; 规划模块是Agent的"大脑"&#xff0c;负责制定行动策略。它接收…

解决vscode中vue格式化后缩进太小的问题,并去除分号 - 设置Vetur tabSize从2到4,设置prettier取消分号semi

效果图 左边原来的&#xff0c;右边是设置后的效果 实现步骤 安装插件 Vetur 安装插件 prettier Vscode > 文件 > 首选项 > 设置 搜索vetur > 找到比较下面的“Vetur > Format > Options: Tab Size” > 设置缩进为4 在附近找到“Vetur > Format: De…

计算机发展史:电子管时代的辉煌与局限

在计算机的发展历程中&#xff0c;电子管时代犹如一颗璀璨的流星&#xff0c;短暂却耀眼。它接过了机械计算装置的接力棒&#xff0c;以电子管为核心元件&#xff0c;开启了计算机的电子化征程&#xff0c;为后续的计算机发展奠定了坚实的基础。这段从 20 世纪 40 年代到 50 年…

div和span区别

区别1区别2App.vue代码 <template><div class"container"><h1>&#x1f3af; DIV 和 SPAN 标签的区别演示</h1><!-- 第一部分&#xff1a;基本区别演示 --><section class"demo-section"><h2>&#x1f4e6; 1. …

channel_up和lane_up

一、channel_up 1.当aurora通道完成初始化&#xff0c;channel准备发送或者接收数据的时候拉高 2.channel_up属于协议的链路层 3.当所有的通道的lane_up都成功拉高&#xff0c;并且完成通道绑定channel bonding,就拉高channel_up二、lane_up 1.lane初始化成功后拉高&#xff1b…

GDPR合规团队协作软件:保障企业数据安全的关键

随着数据隐私问题日益成为全球关注的焦点&#xff0c;GDPR&#xff08;General Data Protection Regulation&#xff0c;通用数据保护条例&#xff09; 的实施成为企业在数据管理中的一项重要法律要求。特别是对于需要在团队之间协作并共享信息的企业来说&#xff0c;选择合规的…

【图像质量评价指标】信噪比(Signal-to-Noise Ratio,SNR)

文章目录一、基本定义二、判断图像信噪比是否过低&#xff08;经验值&#xff0c;仅供参考&#xff09;三、SNR与图像质量指标关系四、评估方法 代码复现 —— 评估一张图像的信噪比&#xff08;1&#xff09;有参考图像&#xff08;推荐&#xff09;&#xff08;2&#xff09…

Java 实现 TCP 一发一收通信

在网络编程中&#xff0c;TCP&#xff08;传输控制协议&#xff09;凭借其可靠传输的特性&#xff0c;成为需要确保数据完整性场景的核心选择。本文将基于一段 Java 代码实例&#xff0c;全面解析 TCP 单向通信的实现逻辑&#xff0c;帮助开发者掌握 TCP 编程的基础框架与底层原…

docker-compose启动前后端分离项目(单机)

&#x1f31f;docker-compose启动前后端 &#x1f4c1;准备文件 xzs-mysql.sql&#xff08;数据库脚本&#xff09;xzs-3.9.0.jar&#xff08;后端代码&#xff09;application-prod.yml&#xff08;后端配置文件&#xff09;entry.sh&#xff08;后端启动脚本&#xff09;exam…

有关Mysql数据库的总结

MySQL概念MySQL的理论知识概念数据库就是用来存储和管理数据的仓库&#xff01;数据库分类层次型数据库树型结构&#xff0c;一个子记录可以有一个父记录&#xff0c;一个父记录可以有多个子记录&#xff0c;类似一个二叉树&#xff0c;但是一个父节点可以不止两个子节点&#…

复制docker根目录遇到的权限问题

环境 ubuntu20.04, 普通用户使用sudo权限。 需求 linux系统上&#xff0c;默认的docker跟目录在/var/lib/docker目录下&#xff0c;但是根分区太小。想要将docker根目录挪到其它磁盘&#xff0c;防止以后镜像和容器增加后磁盘满了。 操作 先停止所有docker容器&#xff0c;然后…

git-子仓操作

为什么为什么要将代码仓作为子模块&#xff1f;有什么优势&#xff1f;精确版本控制&#xff1a;父仓记录子仓的commit哈希值&#xff0c;确保代码版本固定&#xff0c;避免隐式升级导致的兼容性问题模块化管理&#xff1a;将独立仓库作为子模块嵌入父仓&#xff0c;实现代码物…

代数——第5章——线性算子之应用(Michael Artin)

第 5 章 线性算子之应用 (Applications of Linear Operators) By relieving the brain from all unnecessary work, a good notation sets it free to concentrate on more advanced problems.( 通过减轻大脑所有不必要的工作&#xff0c;良好的符号可以让大脑集中精力解决…

Pytorch02:深度学习基础示例——猫狗识别

一、第三方库介绍库/模块功能torch提供张量操作、自动求导、优化算法、神经网络模块等基础设施。torchvision计算机视觉工具集&#xff0c;提供预训练模型、数据集、图像转换等功能。datasets (torchvision)用于加载常见数据集&#xff08;如 ImageNet、CIFAR-10、MNIST&#x…

spring简单项目实战

项目路径 modelspackage com.qcby.demo1;import com.qcby.service.UserService; import com.qcby.service.UserServiceImpl;public class Dfactory {public UserService createUs(){System.out.println("实例化工厂的方式...");return new UserServiceImpl();} }pack…

ServBay for Windows 1.4.0 发布:新增MySQL、PostgreSQL等数据库自定义配置

各位 Windows 平台的开发者们&#xff0c; ServBay 始终致力于为您打造一个强大、高效且灵活的本地开发环境。距离上次更新仅过去短短一周&#xff0c;经过我们技术团队的快速开发&#xff0c;我们正式推出了 ServBay for Windows 1.4.0 版本。 专业开发者不仅需要一个能用的环…

python网络爬虫小项目(爬取评论)超级简单

python网络爬虫小项目&#xff08;爬取评论&#xff09;超级简单 学习python网络爬虫的完整路径&#xff1a; &#xff08;第一章&#xff09; python网络爬虫(第一章/共三章&#xff1a;网络爬虫库、robots.txt规则&#xff08;防止犯法&#xff09;、查看获取网页源代码)-…

本周大模型新动向:奖励引导、多模态代理、链式思考推理

点击蓝字关注我们AI TIME欢迎每一位AI爱好者的加入&#xff01;01Iterative Distillation for Reward-Guided Fine-Tuning of Diffusion Models in Biomolecular Design本文提出了一种用于生物分子设计中奖励引导生成的扩散模型微调框架。扩散模型在建模复杂、高维数据分布方面…