FactoryBean源码解析

news2024/11/25 8:20:45

文章目录

  • 一、简介
  • 二、FactoryBean 接口的方法
  • 三、FactoryBean 与 BeanFactory 的区别
  • 四、源码解析
  • 五、实际应用

一、简介

FactoryBean 是 Spring 框架中的一个接口,用来创建特定类型的 Bean 对象。实现FactoryBean 接口就可以自定义 Bean 对象的创建过程。FactoryBean 本身也是 Bean,会在 Spring 中经历 Bean 的生命周期,而由 FactoryBean 创建的 Bean 不经历 Bean 的生命周期。

二、FactoryBean 接口的方法

FactoryBean 内部包含了一下三个方法:

  • getObject()FactoryBean 最重要的方法,用于返回被管理的Bean对象的实例。
  • getObjectType():返回的 Bean 对象的类型。
  • isSingleton():用于指示返回的 Bean 对象是否为单例。

三、FactoryBean 与 BeanFactory 的区别

有的人分不清 FactoryBeanBeanFactory ,其实只要是粗略看过 Spring 源码的人,都会知道,BeanFactory 是 Spring 容器的顶层接口,这个接口定义了 Spring 容器最基本的功能,如从容器中获取 Bean,判断 Bean 是不是单例等,归根结底它是一个工厂,或者是一个容器,用来创建和管理 Bean 的,而 FactoryBean 是一种特殊的 Bean,注意它是个 Bean,只不过它让我们可以自定义创建 Bean 的过程。

四、源码解析

首先我们先找到 Spring 启动时,初始化 Bean 的核心方法,位于 AbstractApplicationContextrefresh 方法里的 finishBeanFactoryInitialization(beanFactory),在这个方法里,找到最后一行最核心的方法 beanFactory.preInstantiateSingletons() ,在这个方法里,找到下面这段代码。

image-20230719152725153

这段代码是从 Spring 容器里获取所有的非抽象的单例的非懒加载的 Bean,然后判断是不是 FactoryBean,如果不是,就直接调用 getBean 方法完成初始化,如果是,就判断是不是需要紧急初始化。

这里需要注意,FactoryBean 也是做为一个 Bean 放在 Spring 容器里的,从容器里获取这个 FactoryBean 实例,需要在名称前加上 & 符号,如果不加的话,获取的是 FactoryBean 创建出来的 Bean 实例,所以这里通过 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); 这样获取,这个 FACTORY_BEAN_PREFIX 就是 & 符号。

另外这里出现了 SmartFactoryBean 这个接口,这个接口是 FactoryBean 的子接口,其内部通过 isEagerInit 方法来控制是否紧急初始化,所以这里代码的意思就是,如果是 SmartFactoryBean 类型的 FactoryBean 并且 isEagerInit 是 true 的,才会立即调用 getBean 方法完成初始化。

我们继续跟着 getBean 方法往里看

image-20230719155738013

继续跟进 doGetBean,找到创建 Bean 实例的核心代码

image-20230719160208193

在调用完 getSingleton 方法后,会将 FactoryBean 实例放到 Spring 容器里,再调用 getObjectForBeanInstance 方法获取 Bean 实例,我们跟进去看看

image-20230719161353731

继续跟进

image-20230719161649962

第一个if判断,用处是防止那种不是 FactoryBean,但是前面带了 & 符号进来的。

第二个if判断,就是如果是普通的 bean 或者是 FactoryBean,就返回其实例本身,这就是我们上面说的,如果 FactoryBeanbeanName 前面带了 & 符号,就返回 FactoryBean 本身。

能继续往下走,就说明一定是 FactoryBean 了,所以类型强转后,调用 getObjectFromFactoryBean 方法,我们继续跟进

image-20230719162451554

这里用了一些缓存的机制,我们不用管,继续跟进 doGetObjectFromFactoryBean 方法

image-20230719162647762

我们可以看到,最终调用了 FactoryBeangetObject 方法

五、实际应用

FactoryBean 的实际应用场景有很多,例如 SpringAop 的 ProxyFactoryBean 用来创建 AOP 代理,Mybatis 的 MapperFactoryBean 用来创建 Mapper 的代理对象,Fegin 的 FeignClientFactoryBean 用来创建远程服务代理。

有兴趣的小伙伴,可以在任意一个 FactoryBeangetObject() 方法上打上断点,启动服务,看看具体的方法调用栈,可以更好的帮助学习源码。

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

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

相关文章

深入浅出如何通过API瞬间搭建亿万商品外贸代购系统PHP系统

什么是淘宝代购 淘宝代购是近年兴起的一种购物模式,是帮国外客户购买中国商品。主要是通过万邦 科技的外贸代购系统,把淘宝、天猫等电商平台的全站商品通过API 接入到你的网站 上,瞬间就可以架设一个有数亿产品的大型网上商城,而…

【Leetcode】687.最长同值路径

一、题目 1、题目描述 给定一个二叉树的 root ,返回 最长的路径的长度 ,这个路径中的 每个节点具有相同值 。 这条路径可以经过也可以不经过根节点。 两个节点之间的路径长度 由它们之间的边数表示。 示例1: 输入:root = [5,4,5,1,1,5] 输出:2示例2: 输入:root …

IT技术岗的面试技巧分享

我们在找工作时,需要结合自己的现状,针对意向企业做好充分准备。作为程序员,你有哪些面试IT技术岗的技巧?你可以从一下几个方向谈谈你的想法和观点。 方向一:分享你面试IT公司的小技巧 1、事先和邀约人了解公司的基本情况,比如公司的行业,规模,研发人员占比等 2、事先和…

甲板上的战舰(力扣)递归 JAVA

给你一个大小为 m x n 的矩阵 board 表示甲板,其中,每个单元格可以是一艘战舰 ‘X’ 或者是一个空位 ‘.’ ,返回在甲板 board 上放置的 战舰 的数量。 战舰 只能水平或者垂直放置在 board 上。换句话说,战舰只能按 1 x k&#xf…

华为OD机试真题 Java 实现【最左侧冗余覆盖子串】【2023Q2 100分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、思路 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷&#…

C++-----vector

本期我们来学习C中的vector,因为有string的基础,所以我们会讲解的快一点 目录 vector介绍 vector常用接口 构造函数 sort 迭代器 size,max_size,capacity,empty reserve和resize front和back data insert和…

VUE- 选取本地图片,自定义裁切图片比例 vue-cropper

裁切图片,按照比例裁切,分步骤 1:el-upload选择本地图片(分选择本地和上传两步骤) 2:在on-change回调方法中拿到el-upload选中的图片,显示在vueCropper上()。 2.1&…

为什么互联网网络攻击总是在瞄准金融行业

自从网络时代开始,金融行业一直是最容易被攻击的几个行业之一,它占火伞云相关跟踪攻击尝试的28%,仅次于游戏行业。随着网络犯罪的增长,金融服务业将继续成为网络攻击者的重点目标。 攻击者出于多种原因瞄准金融领域,但…

STM32—CAN通信

文章目录 一、CAN通信简介1.1 CAN简介1.2 CAN协议特点1.3 CAN通信的帧类型1.4 数据帧结构1.5 CAN的位时序1.6 CAN的仲裁功能 二、STM32F1的CAN2.1 bxCAN简介2.2 bxCAN工作模式2.2.1 初始化模式2.2.2 正常模式2.2.3 睡眠模式2.2.4 静默模式2.2.5 环回模式 2.3 位时序和波特率 三…

Spring(一):Spring 的创建和使用

目录 Spring 是什么? 什么是容器? 什么是 IoC? 什么是 IoC? IoC的优点是啥呢? 理解 IoC DI 概念说明 Spring 的创建 创建 Spring 项目 1. 创建⼀个普通 Maven 项⽬。 2. 添加 Spring 框架⽀持(s…

谈一谈,Spring Boot 中的 starter 到底是什么 ?

1. 为什么要用Starter? 现在我们就来回忆一下,在还没有Spring-boot框架的时候,我们使用Spring 开发项目,如果需要某一个框架,例如mybatis,我们的步骤一般都是:到maven仓库去找需要引入的mybatis jar包&am…

【UE5 多人联机教程】01-创建主界面

目录 工程地址 步骤 参考链接 工程地址 GitHub - UE4-Maple/C_MP_Lobby: 多人大厅教程项目 步骤 1. 先新建一个工程 2. 将下载的工程中的Plugins目录拷贝到自己新建的工程下 3. 打开工程,新建一个游戏实例 这里命名为“GI_Main” 在项目设置中设置游戏实例类为…

排序算法之快速排序举例详解-python实现3版代码及改进过程

快速排序思想步骤: 1.找到一个基准值key 2.设置2个元素下标i0和jlen-1 3.从后往前找到比key小的数num[j],从前往后找到比key大的数num[i](这里有个先后顺序) 4.交换这两个数:num[i],num[j] 5.继续重复…

如何在PADS Logic中查找器件

PADS Logic提供类似于Windows的查找功能,可以进行器件的查找。 (1)在Logic设计界面中,将菜单显示中的“选择工具栏”进行打开,如图1所示,会弹出对应的“选择工具栏”的分栏菜单选项,如图2所示。…

数据库信息速递 MONGODB 6.0 的新特性,更多的查询函数,加密查询,与时序数据集合 (译)...

开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到3群(共…

Shell脚本函数 实验

Shell 函数 命令序列按照格式写在一起,用函数的方式调用并进行重复使用命令序列。这就是它的核心作用 使用函数可以避免代码重复,函数可以将大的工程分割成若干小的功能模块,提高代码的可读性。 函数的基本格式写法有两种,如下&…

零钱兑换 II(力扣)动态规划 JAVA

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带符号整数。 示例…

预付费电表收费系统

预付费电表收费系统是一种先进的电表管理系统,它能够帮助电力公司更加高效地管理电表收费,提高用电效率,降低能源浪费。本文将从以下几个方面介绍预付费电表收费系统的特点和优势。 一、预付费电表收费系统的原理 预付费电表收费系统是指用户…

5分钟给你破解这套10万赞的生产教程,访谈乔布斯的AI对话数字人视频是怎么做的

本期是赤辰第16期AI项目拆解栏目; 底部准备了7月粉丝福利,看完可以领取; 上周给粉丝们讲解AI动图说话月涨粉20万的案例并给出保姆式教程,粉丝反馈很热烈,都觉得AI强大,有些学员给自己账号做视频&#xff…

ACME申请SSL证书

1.开放443端口 firewall-cmd --permanent --add-port443/tcp # 开放443端口 firewall-cmd --reload # 重启防火墙(修改配置后要重启防火墙)2.安装ACME # 安装acme curl https://get.acme.sh | sh -s email你的邮箱地址 # 别名 alias acme.sh~/.acme.sh/acme.sh3.使用ACME申请…