浅析 Spring 中 FactoryBean 的实现与使用

浅析 Spring 中 FactoryBean 的实现与使用

  • 一、FactoryBean核心机制剖析
  • 二、高级应用场景与实战
  • 三、框架级应用案例解析
  • 四、FactoryBean常见面试题

在这里插入图片描述

一、FactoryBean核心机制剖析

1. 本质与双重角色

FactoryBean是Spring容器中用于定制化对象创建的核心接口(org.springframework.beans.factory.FactoryBean),其设计体现了两个关键特征:

  • 工厂模式:通过getObject()方法动态生成目标对象
  • 容器托管:FactoryBean本身作为Spring Bean被容器管理,支持依赖注入和生命周期回调

2. 接口方法详解

public interface FactoryBean<T> {T getObject() throws Exception;    // 核心工厂方法Class<?> getObjectType();          // 决定自动注入的类型匹配default boolean isSingleton() {    // 控制对象作用域return true;}
}

运行机制:
Spring容器初始化时,若检测到Bean实现FactoryBean接口,会通过getObject()生成目标对象。通过&前缀获取工厂实例本身(如getBean("&myFactory")

3. 源码级工作流程

参考Spring源码的Bean创建流程:

  1. Bean实例化AbstractAutowireCapableBeanFactory.createBeanInstance()创建FactoryBean实例
  2. 对象生成:在getObjectForBeanInstance()方法中调用getObject()生成目标对象
  3. 缓存处理:单例对象存入factoryBeanObjectCache,多例对象每次新建

关键源码片段(简化):

// AbstractBeanFactory.doGetBean()
Object beanInstance = getSingleton(beanName);
if (beanInstance instanceof FactoryBean) {return getObjectFromFactoryBean((FactoryBean<?>) beanInstance, beanName);
}

二、高级应用场景与实战

1. 多例对象动态生成

public class PrototypeToolFactory implements FactoryBean<Tool> {@Override public boolean isSingleton() {return false; // 每次请求新实例}@Overridepublic Tool getObject() {return new Tool(UUID.randomUUID().toString());}
}

应用场景:数据库连接池、线程不安全对象的按需创建

2. 手动配置代理(AOP场景)

(ProxyFactoryBean 是 Spring AOP 中用于 手动配置代理对象的核心类;而动态代理底层是基于AnnotationAwareAspectJAutoProxyCreator实现)

public class ServiceProxyFactory implements FactoryBean<Object> {private Object target;@Overridepublic Object getObject() {return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),(proxy, method, args) -> {System.out.println("[Before] Method: " + method.getName());Object result = method.invoke(target, args);System.out.println("[After] Result: " + result);return result;});}
}

实现原理:Spring AOP的ProxyFactoryBean即采用类似机制生成代理对象

3. 延迟初始化策略

public class LazyDataSourceFactory implements FactoryBean<DataSource> {private boolean initialized = false;private DataSource dataSource;@Overridepublic DataSource getObject() {if (!initialized) {initializeDataSource(); // 首次调用时初始化initialized = true;}return dataSource;}
}

优势:优化启动速度,按需加载重量级资源

三、框架级应用案例解析

1. MyBatis SqlSessionFactoryBean

核心逻辑:

  • 实现InitializingBean确保属性设置完成后构建SqlSessionFactory
  • 通过buildSqlSessionFactory()解析XML配置、Mapper映射
  • 集成Spring事务管理

2. Spring Cloud FeignClientFactoryBean

实现机制:

  • 动态生成Feign客户端接口代理
  • 整合Ribbon负载均衡、Hystrix熔断
  • 通过Targeter.target()生成最终代理对象

3. Spring AOP ProxyFactoryBean

(ProxyFactoryBean 是 Spring AOP 中用于 手动配置代理对象的核心类;而动态代理底层是基于AnnotationAwareAspectJAutoProxyCreator实现)

<bean id="personTarget" class="com.example.PersonImpl"/>
<bean id="myAdvisor" class="com.example.MyAdvisor"/><bean id="personProxy" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="personTarget"/><property name="proxyInterfaces" value="com.example.Person"/><property name="interceptorNames"><list><value>myAdvisor</value></list></property>
</bean>

工作流程:

  • 配置Advisor(切面)和Advice(增强)
  • 通过getObject()生成JDK/CGLIB代理
  • 将拦截器链织入代理对象

四、FactoryBean常见面试题

1. BeanFactory 和 FactoryBean 的区别?

维度BeanFactoryFactoryBean
角色Spring 容器根接口,管理所有 Bean特殊 Bean,用于生成其他对象
获取方式getBean(“beanName”) 直接获取 BeangetBean(“beanName”) 获取目标对象,&beanName 获取工厂
设计目标提供容器基础功能(如依赖注入)扩展复杂对象的创建逻辑(如代理、动态配置)
典型实现ApplicationContextSqlSessionFactoryBean、ProxyFactoryBean

2. FactoryBean 的初始化时机?

  • 普通 Bean 阶段:FactoryBean 实例在 Spring 容器初始化时创建。
  • 目标对象阶段:目标对象(getObject() 生成)在首次调用 getBean() 时创建,支持懒加载(@Lazy)。 源码位置:AbstractBeanFactory.getObjectForBeanInstance()getObjectFromFactoryBean()

3. 如何通过 FactoryBean 实现多例对象?

  • 重写方法isSingleton() 返回 false,每次调用 getObject() 生成新实例。

  • 示例

    public class PrototypeFactory implements FactoryBean<MyObject> {@Overridepublic boolean isSingleton() { return false; }@Overridepublic MyObject getObject() { return new MyObject(); }
    }
    

应用场景:线程不安全对象(如数据库连接)、动态配置对象

4. FactoryBean 在 MyBatis 中的应用?

  • 案例:SqlSessionFactoryBean
  • 核心流程
    • 实现 FactoryBean<SqlSessionFactory>,在 getObject() 中解析 MyBatis 配置。
    • 集成 Spring 事务管理,通过 InitializingBean 确保属性初始化完成

5. 如何获取 FactoryBean 自身实例?

  • 语法:在 Bean 名称前添加 & 前缀,例如 context.getBean("&myFactory")
  • 原理:Spring 容器通过 BeanFactory.FACTORY_BEAN_PREFIX 标识工厂实例

6. FactoryBean 与 @Bean 注解的区别?

维度FactoryBean@Bean
实现方式需实现接口,编写 getObject() 逻辑通过注解声明,直接返回对象实例
对象生成动态生成(如代理、复杂初始化)直接实例化(简单对象)
获取方式beanName 获取目标对象,&beanName 获取工厂直接通过 beanName 获取实例
生命周期支持单例/多例控制默认单例,可通过 @Scope 修改

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

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

相关文章

vue3 element-plus 输入框回车跳转页面问题处理

问题描述&#xff1a; 当页面搜索条件只有一个的情况下&#xff0c;输入框不管有没有值&#xff0c;回车后会跳转页面 解决办法&#xff0c;给表单添加 submit.prevent <el-form ref"ruleForm" :model"search" label-width"120px" class&qu…

(51单片机)LCD展示动画(延时函数)(LCD1602教程)

前言&#xff1a; 前面我们说过&#xff0c;之前LCD1602模块有点难&#xff0c;但是现在&#xff0c;我们通过几遍博客的学习&#xff0c;今天来讲一下LCD1602的原理 演示视频&#xff1a; LCD1602流动 源代码&#xff1a; main.c #include <STC89C5xRC.H> #include &q…

深入了解 OpenIddict:实现 OAuth 2.0 和 OpenID Connect 协议的 .NET 库

在现代 Web 开发中&#xff0c;身份验证和授权是安全性的重要组成部分。随着对安全性的要求不断增加&#xff0c;OAuth 2.0 和 OpenID Connect&#xff08;OIDC&#xff09;协议已经成为许多应用程序的标准身份验证方式。而 OpenIddict&#xff0c;作为一个用于实现 OAuth 2.0 …

【C++游戏引擎开发】第30篇:物理引擎(Bullet)—软体动力学系统

一、软体动力学理论体系 1.1 连续体力学基础 1.1.1 变形梯度张量 物体运动可描述为映射函数: x = ϕ ( X , t ) \mathbf{x} = \phi(\mathbf{X},t) x

Android Compose 层叠布局(ZStack、Surface)源码深度剖析(14)

Android Compose 层叠布局&#xff08;ZStack、Surface&#xff09;源码深度剖析 一、引言 在 Android 应用开发领域&#xff0c;用户界面&#xff08;UI&#xff09;的设计与实现一直是至关重要的环节。随着技术的不断演进&#xff0c;Android Compose 作为一种全新的声明式…

性能优化实践:内存优化技巧

性能优化实践&#xff1a;内存优化技巧 在Flutter应用开发中&#xff0c;内存优化是提升应用性能的关键环节之一。本文将从实战角度深入探讨Flutter内存优化的各种技巧&#xff0c;帮助你构建高性能的Flutter应用。 一、内存分析工具使用 1. DevTools内存分析器 启动DevTool…

2025-05-07 Unity 网络基础8——UDP同步异步通信

文章目录 1 UDP 概述1.1 通信流程1.2 TCP 与 UDP1.3 UDP 分包1.4 UDP 黏包 2 同步通信2.1 服务端2.2 客户端2.3 测试 3 异步通信3.1 Bgin / End 方法3.2 Async 方法 1 UDP 概述 1.1 通信流程 ​ 客户端和服务端的流程如下&#xff1a; 创建套接字 Socket。用 Bind() 方法将套…

如何减少锁竞争并细化锁粒度以提高 Rust 多线程程序的性能?

在并发编程中&#xff0c;锁&#xff08;Lock&#xff09;是一种常用的同步机制&#xff0c;用于保护共享数据免受多个线程同时访问造成的竞态条件&#xff08;Race Condition&#xff09;。然而&#xff0c;不合理的锁使用会导致严重的性能瓶颈&#xff0c;特别是在高并发场景…

AGV智能搬运机器人:富唯智能引领工业物流高效变革

在智能制造与工业4.0深度融合的今天&#xff0c;物流环节的高效与精准已成为企业核心竞争力的关键。富唯智能凭借其自主研发的AGV智能搬运机器人&#xff0c;以创新技术重塑工业物流标准&#xff0c;助力企业实现降本增效的跨越式发展。 一、技术突破&#xff1a;精准导航与智能…

K8s 资源分类

K8s 资源分类图谱 内置资源的分类 1、工作负载相关&#xff1a; Pod&#xff1a;最小的部署单元&#xff0c;包含一个或多个容器。 Deployment&#xff1a;管理无状态应用的副本和滚动更新。 StatefulSet&#xff1a;适用于有状态应用&#xff08;如数据库&#xff09;&#…

VLM-AD:通过视觉语言模型监督实现端到端自动驾驶

《VLM-AD: End-to-End Autonomous Driving through Vision-Language Model Supervision》2024年12月发表&#xff0c;来自Cruise和美国东北大学的论文。 人类驾驶员依靠常识推理来驾驭多样化和动态的现实世界场景。现有的端到端&#xff08;E2E&#xff09;自动驾驶&#xff0…

目标检测中的损失函数(三) | SIoU WIoUv1 WIoUv2 WIoUv3

&#x1f680;该系列将会持续整理和更新BBR相关的问题&#xff0c;如有错误和不足恳请大家指正&#xff0c;欢迎讨论&#xff01;&#xff01;&#xff01; SCYLLA-IoU&#xff08;SIoU&#xff09;来自挂在2022年arxiv上的文章&#xff1a;《SIoU Loss: More Powerful Learnin…

http Status 400 - Bbad request 网站网页经常报 HTTP 400 错误,清缓存后就好了的原因

目录 一、HTTP 400 错误的常见成因(一)问题 URL(二)缓存与 Cookie 异常(三)请求头信息错误(四)请求体数据格式不正确(五)文件尺寸超标(六)请求方法不当二、清缓存为何能奏效三、其他可以尝试的解决办法(一)重新检查 URL(二)暂时关闭浏览器插件(三)切换网络环…

【DeepMLF】具有可学习标记的多模态语言模型,用于情感分析中的深度融合

这是一篇我完全看不懂的论文,写的好晦涩,适合唬人,所以在方法部分我以大白话为主 abstract 在多模态情感分析(MSA)中,多模态融合已经得到了广泛的研究,但融合深度和多模态容量分配的作用还没有得到充分的研究。在这项工作中,我们将融合深度、可扩展性和专用多模容量作…

【ASP.net】在Windows 11上安装IIS并测试C# Web项目的踩坑实录

摘要 多年未接触.NET技术栈的田辛老师&#xff0c;最近因项目需求重新搭建测试环境。本文记录了Windows 11环境下安装IIS服务的全过程&#xff0c;以及一个让开发者抓狂的“空白页面”问题的解决方案。 1. 基础环境配置 工欲善其事&#xff0c;必先利其器。本次环境搭建选择…

【IP101】图像特征提取技术:从传统方法到深度学习的完整指南

&#x1f31f; 特征提取魔法指南 &#x1f3a8; 在图像处理的世界里&#xff0c;特征提取就像是寻找图像的"指纹"&#xff0c;让我们能够识别和理解图像的独特性。让我们一起来探索这些神奇的特征提取术吧&#xff01; &#x1f4da; 目录 基础概念 - 特征的"体…

HybridCLR 详解:Unity 全平台原生 C# 热更新方案

HybridCLR&#xff08;原 Huatuo&#xff09;是 Unity 平台革命性的热更新解决方案&#xff0c;它通过扩展 Unity 的 IL2CPP 运行时&#xff0c;实现了基于原生 C# 的完整热更新能力。下面从原理到实践全面解析这一技术。 一、核心原理剖析 1. 技术架构 原始 IL2CPP 流程&am…

机器学习——逻辑回归ROC练习

一、 题目要求&#xff1a; 给定以下二分类模型的预测结果&#xff0c;手动绘制ROC曲线并计算AUC值&#xff1a; y_true [0, 1, 0, 1, 0, 1] # 真实标签&#xff08;0负类&#xff0c;1正类&#xff09; y_score [0.2, 0.7, 0.3, 0.6, 0.1, 0.8] # 模型预测得分 代码展示…

Python项目源码69:Excel数据筛选器1.0(tkinter+sqlite3+pandas)

功能说明&#xff1a;以下是一个使用Tkinter和Pandas实现的完整示例&#xff0c;支持Excel数据读取、双表格展示和高级条件筛选功能&#xff1a; 1.文件操作&#xff1a;点击"打开文件"按钮选择Excel文件&#xff08;支持.xlsx和.xls格式&#xff09;&#xff0c;自…

php8 枚举使用教程

简介 PHP 从 8.1 开始原生支持枚举&#xff08;enum&#xff09;&#xff0c;这是 PHP 向类型安全和现代语言特性迈进的重要一步。枚举可以定义一组有穷的、不可变的常量集合&#xff0c;常用于表示状态值、选项类型等。 基础语法 PHP 支持两种类型的枚举&#xff1a; 纯枚…