内容介绍

在 Spring 框架中,FactoryBean 是一个特殊的工厂类接口,用于创建和管理复杂的 bean 对象。它允许你自定义 bean 的创建逻辑,并且可以在 bean 创建过程中执行一些额外的操作。FactoryBean 接口通常用于创建那些非常复杂或需要特殊处理的 bean 实例,例如连接池、远程服务代理等。

        当我们向容器中获取FactoryBean时,容器返回的不是他本身,而是他的getObject()方法的返回值。

FactoryBean 接口有两个核心方法:

  1. T getObject():该方法负责创建和返回一个 bean 实例。你可以在这个方法中编写自定义的 bean 创建逻辑。

  2. Class<?> getObjectType():该方法返回工厂创建的 bean 的类型。通常,它用于告诉 Spring 容器工厂创建的 bean 类型是什么。

代码分支

https://github.com/yihuiaa/little-spring/tree/factory-beanhttps://github.com/yihuiaa/little-spring/tree/factory-bean

核心代码

FactoryBean接口

public interface FactoryBean<T> {

	T getObject() throws Exception;

	boolean isSingleton();
}

AbstractBeanFactory

在getBean方法中添加BeanFactory的逻辑,当bean属于BeanFactory类型的,就拿他的getObject方法返回的对象,并根据isSingleton()方法返回时决定是否加入缓存。

....
用于缓存单例的BeanFactory提供类
private final Map<String, Object> factoryBeanObjectCache = new HashMap<>(); private Object getObjectForBeanInstance(Object sharedInstance, String beanName) throws Exception {
Object obj = sharedInstance;
if(sharedInstance instanceof FactoryBean){
try {
FactoryBean factoryBean = (FactoryBean<?>)sharedInstance;
if(((FactoryBean<?>)sharedInstance).isSingleton()){
//singleton作用域bean,从缓存中获取
obj = this.factoryBeanObjectCache.get(beanName);
if( obj == null ){
obj = factoryBean.getObject();
this.factoryBeanObjectCache.put(beanName, obj);
}
}else{
//prototype作用域bean,新创建bean
obj = factoryBean.getObject();
}
}catch (Exception e){
throw new BeansException("FactoryBean threw exception on object[" + beanName + "] creation", e);
}
}
return obj;
} ....

测试

xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="person" class="bean.PersonFactoryBean">
<property name="name" value="yiHuiGoGoGO"/>
</bean> </beans>

FactoryBean

public class PersonFactoryBean implements FactoryBean<Person> {
private String name; @Override public Person getObject() {
Person person = new Person();
person.setName("YiHuiComeOn");
person.setAge("18");
return person;
}
@Override public boolean isSingleton() {
return true;
}
....

测试类

	@Test
public void testFactoryBean(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:factory-bean.xml");
Person person = applicationContext.getBean("person", Person.class);
System.out.println(person);
}

测试结果

输出的确实是getObject返回的类,而不是类本身。

Person{name='YiHuiComeOn', age='18', car=null}

[源码系列:手写spring] IOC第十二节:FactoryBean的更多相关文章

  1. Spring源码分析 手写简单IOC容器

    Spring的两大特性就是IOC和AOP. IOC Container,控制反转容器,通过读取配置文件或注解,将对象封装成Bean存入IOC容器待用,程序需要时再从容器中取,实现控制权由程序员向程序的 ...

  2. 《四 spring源码》手写springioc框架

    手写SpringIOCXML版本 /** * 手写Spring专题 XML方式注入bean * * * */ public class ClassPathXmlApplicationContext { ...

  3. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

  4. 从零开始手写 spring ioc 框架,深入学习 spring 源码

    IoC Ioc 是一款 spring ioc 核心功能简化实现版本,便于学习和理解原理. 创作目的 使用 spring 很长时间,对于 spring 使用非常频繁,实际上对于源码一直没有静下心来学习过 ...

  5. 框架源码系列六:Spring源码学习之Spring IOC源码学习

    Spring 源码学习过程: 一.搞明白IOC能做什么,是怎么做的  1. 搞明白IOC能做什么? IOC是用为用户创建.管理实例对象的.用户需要实例对象时只需要向IOC容器获取就行了,不用自己去创建 ...

  6. 《四 spring源码》手写springmvc

    手写SpringMVC思路 1.web.xml加载  为了读取web.xml中的配置,我们用到ServletConfig这个类,它代表当前Servlet在web.xml中的配置信息.通过web.xml ...

  7. Spring源码 20 手写模拟源码

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  8. 利用递归,反射,注解等,手写Spring Ioc和Di 底层(分分钟喷倒面试官)了解一下

    再我们现在项目中Spring框架是目前各大公司必不可少的技术,而大家都知道去怎么使用Spring ,但是有很多人都不知道SpringIoc底层是如何工作的,而一个开发人员知道他的源码,底层工作原理,对 ...

  9. Spring源码剖析3:Spring IOC容器的加载过程

    本文转自五月的仓颉 https://www.cnblogs.com/xrq730 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https ...

  10. 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)

    作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言介绍 一个知识点的学习过程基本分为:运行helloworld ...

随机推荐

  1. CF div3 995 (A~G)

    期末周之第三把网瘾(真是越来越放肆了...).这次赛时了一把div 3 , 又一次只做出了A~E,写完E后剩下的题没时间看了(受了些寝室噪音的干扰,最后二十分钟才出).赛后看了下F和G,感觉也是一时半 ...

  2. Springboot集成-ClickHouse

    1.clickhouse应⽤场景 1.绝大多数请求都是用于读访问的 2.数据需要以大批次(大于1000行)进行更新,而不是单行更新:或者根本没有更新操作 3.数据只是添加到数据库,没有必要修改 4.读 ...

  3. weixueyuan-Nginx HTTP模块3

    https://www.weixueyuan.net/nginx/http/ Nginx镜像模块:ngx_http_mirror_module Nginx 中镜像模块的功能是将用户的访问请求镜像复制到 ...

  4. 在没有网关的IP地址上编写路由,实现另一个网段可以访问到该主机

    应用场景:该主机两个网卡分别对应两个IP地址 192.168.1.2网段为医保网,并且主机使用了改网段的的网关.192.168.100.99网段地址为互联网地址,没有使用该网段的网关. 我们开发小组通 ...

  5. 浅说TCP状态机制

    本文分享自天翼云开发者社区<浅说TCP状态机制>,作者:云云生息 TCP(Transmission Control Protocol)是一种面向连接的.可靠的传输协议,常用于互联网中应用层 ...

  6. [记录点滴] luaxml编译过程

    [记录点滴] luaxml编译 记录一次luaxml编译的解决过程 参考 http://blog.csdn.net/dc_show/article/details/38957991 0x01 编译错误 ...

  7. Q:plsql中文显示??处理

    1.查询数据库字符集select userenv('language') from dual; 2.修改NLS_LANG环境变量:将NLS_LANG环境变量设置为正确的字符集 windows设置系统环 ...

  8. 这或许是全网最全的 DeepSeek 使用指南,95% 的人都不知道的使用技巧(建议收藏)

    2025年春节过的好快,转眼间,大家又回到了各自工作岗位了,要说这个春节,什么最火,肯定绕不开DeepSeek. 几乎一夜之间,所有人都在关注DeepSeek,甚至我在老家,完全没用过AI的七大姑八大 ...

  9. gitlab - [02] 安装部署

    安装部署篇 一.5分钟搭建私人代码仓库 (1)设置环境变量:export GITLAB_HOME=/src/gitlab (2)编写docker-compose.yml mkdir -p /opt/d ...

  10. Kubernetes - [02] 网络通讯方式

    题记部分 一.网络通讯模式   Kubernetes的网络模型假定了所有Pod都在一个可以直接连通的扁平的网络空间中,这在(GCEGoogle Compute Engine)里面是现成的网络模型,Ku ...