Spring源码之FactoryBean接口的作用和实现原理

1.FactoryBean 接口简述

BeanFactoryFactoryBean 接口,相信很多刚翻看 Spring 源码跟我一样很好奇这俩货怎么长得这么像,分别都是干啥用的。BeanFactorySpringBean 工厂的顶层接口,也是我们常说的 Spring IOC 容器,它定下了 IOC 容器的一些规范和常用方法并管理着 Spring 中所有的 Bean,今天我们不讲它,我们看一下后面那个 FactoryBean

public interface FactoryBean<T> {
   

	@Nullable
	T getObject() throws Exception;

	@Nullable
	Class<?> getObjectType();

	default boolean isSingleton() {
   
		return true;
	}
}

先说下 FactoryBean 和其作用再开始分析:首先它是一个 Bean,但又不仅仅是一个 Bean。它是一个能生产或修饰对象生成的工厂 Bean,类似于设计模式中的工厂模式和装饰器模式。它能在需要的时候生产一个对象,且不仅仅限于它自身,它能返回任何 Bean 的实例

2.FactoryBeanSpring 中的应用

Spring 中我们的 Bean 都会被 SpringIOC 容器所管理,在 AbstractApplicationContext 中有一个很重要的方法:refresh(),项目启动或重启的时候 refresh() 会调用 getBean() 初始化所有的 Bean,这个 getBean() 最终会指向 AbstractBeanFactory 中的 getBean() 方法。上述方法的调用链过长,我们不过多赘述,详细的 getBean() 源码 在这里

AbstractBeanFactory 抽象类中,不管是根据名称还是根据类型,getBean() 方法最终都会调用 doGetBean() 方法

2.1.doGetBean()

doGetBean() 方法中一开始就获取了名称 beanName 和实例 sharedInstance

@SuppressWarnings("unchecked")
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 bean;

	// 方法解释如下图
	Object sharedInstance = getSingleton(beanName);
	// 如果已经初始化过,直接从缓存中获取
	if (sharedInstance != null && args == null) {
   
		if (logger.isDebugEnabled()) {
   
			if (isSingletonCurrentlyInCreation(beanName)) {
   
				logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
						"' that is not fully initialized yet - a consequence of a circular reference");
			}
			else {
   
				logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
			}
		}	
		// 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果
		// 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的 bean 实例
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}
	else {
   
		// 如果是原型不应该在初始化的时候创建,在这里直接抛出异常
		if (isPrototypeCurrentlyInCreation(beanName)) {
   
			throw new BeanCurrentlyInCreationException(beanName);
		}
		BeanFactory parentBeanFactory = getParentBeanFactory();
		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
   
			// 将别名解析成真正的beanName
			String nameToLookup = originalBeanName(name);
			// 如果parentBeanFactory存在,并且beanName在当前BeanFactory不存在Bean定义,则尝试从parentBeanFactory中获取bean实例
			if (parentBeanFactory instanceof AbstractBeanFactory) {
   
				return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
						nameToLookup, requiredType, args, typeCheckOnly);
			}
			// 尝试在parentBeanFactory中获取bean对象实例
			else if (args != null) {
   
				return (T) parentBeanFactory.getBean(nameToLookup, args);
			}
			else {
   
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
		}
		if (!typeCheckOnly
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值