Spring - FactoryBean


FactoryBean接口

FactoryBean接口很简单,定义了如下几个方法

public interface FactoryBean<T> {


	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";


	/**
	 * 返回创建的Bean对象
	 */
	@Nullable
	T getObject() throws Exception;

	/**
	* 返回对象的类型
	*/
	@Nullable
	Class<?> getObjectType();

	/**
	*是否单例
	*/
	default boolean isSingleton() {
		return true;
	}

FactoryBean的使用

FactoryBean用于手动控制一个Bean的创建,相对于正常的SpringBean,可以更加自由的指定Bean的创建。

示例

@Component("userFromFactory")
public class MyFactoryBean implements FactoryBean<User> {


	@Override
	public User getObject() {
		return new User();
	}

	@Override
	public Class<?> getObjectType() {
		return User.class;
	}
}

测试类

public class Test {

	/**
	 *
	 */
	public static void main(String[] args) {

		// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

		User userFromFactory = applicationContext.getBean("userFromFactory", User.class);
		System.out.println(userFromFactory);
		}
	}

输出结果
在这里插入图片描述可以

可以看到,成功创建了User对象,并从容器中可以根据BeanFactory的名称获取到生产的Bean。
这与我们一般getBean的结果不太一样,一般我们根据beanName获取到的是Bean本身,让我们接
着看getBean("$userFromFactory")的结果
在这里插入图片描述
此时没有返回生产的Bean,而是直接返回了FactoryBean对象本身,我们可以猜测:
FactoryBean在IOC容器内是‘&name’的形式存储,而生产的Bean是以'name'的形式存储

究竟是不是这样呢?让我们看getBean方法

源码解析

1. 获取&userFromFactory

首先,我们看getBean是如何获取&userFromFactory对象的
在这里插入图片描述

进入方法可以看到第一步transformedBeanName方法把&userFromFactory转换成了userFromFactory,接着从
对象池中获取到了FactoryBean对象
在这里插入图片描述

获取到之后并没有直接返回,进了getObjectForBeanInstance方法
在这里插入图片描述

这里BeanFactoryUtils.isFactoryDereference(name)先判断了beanName是否是以&开头,如果是以&开头,直接将前面从对象池中获取到的Bean返回,所以直接从此返回了FactoryBean对象。

我们可以得出部分结论:在IOC容器中FactoryBean对象是跟本身名称映射的,而不是跟&name

去容器中验证一下,确实如此
在这里插入图片描述

2. 获取userFromFactory(生产出的对象)

前面的步骤一样,当我们走到getObjectForBeanInstance方法后
在这里插入图片描述

尝试从缓存中取对象(思考一下也比较合理,因为factoryBean同样可以被定义为单例,自然应该有对应的缓存池),当我们首次获取时是没有值的,所以继续往下走

在这里插入图片描述
在这里插入图片描述

最终是通过getObjectFromFactoryBean -> doGetObjectFromFactoryBean 中调用了facotryBean本身的getObject对对象进行了创建,并且创建后放到缓存中保证单例唯一性。

结论

在这里插入图片描述FactoryBean的对象池跟IOC容器并不在一起,是单独保存在FactoryBeanRegistrySupport类的factoryBeanObjectCache
在这里插入图片描述

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值