FactoryBean的使用

BeanFactory

 BeanFactory是接口,用于管理Bean的一个工厂。BeanFactory是IOC容器的核心接口,它主要作用就是实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

  BeanFactory只是一个接口,并不是IOC容器的具体实现,Springp容器提供了很多种实现,如:XmlBeanFactory、ApplicationContext等。现在一般使用ApplicationContext,它包含了原始的BeanFactory的所有功能,同时还进行了扩展,如AOP功能、web应用等。XmlBeanFactory类似以XML配置元数据,实现将以XML方式描述组成的对象及对象间的依赖关系。

FactoryBean

FactoryBean也是接口,实现此接口的类也是一种Bean。Spring中共有二种bean,一种是普通bean(就是上面说的BeanFactory管理的bean),另一种是实现FactoryBean接口的Bean。FactoryBean管理的Bean实际上也是由spring进行管理、实例化,配置,因此由FactoryBean管理的Bean不能再次配置到Spring配置文件中,否则会报异常。

 从Spring的applicationContext或BeanFactory获取bean时,获取到是FactoryBean创建的实例,而不是FactoryBean自己,如果想通过spring拿到FactoryBean,需要在名称前面加&符号。

FactoryBean在IOC的应用,在我们获取Bean的时候,都会经过getObjectForBeanInstance方法,这个方法会进行如下判断:

  • 如果bean是被FactoryBean引用,但bean对象不是Factory,则抛出异常(BeanIsNotAFactoryException);也就是说通过FactoryBean获取bean,这个bean不能配置到spring配置文件或者注解实例化;
// 如果指定的name是工厂相关的(&前缀),并且beanInstance又不是FactoryBean类 则验证不通过
if (BeanFactoryUtils.isFactoryDereference(name)) {
	if (beanInstance instanceof NullBean) {
		return beanInstance;
	}
	if (!(beanInstance instanceof FactoryBean)) {
		throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
	}
}

 

  • 如果Bean实例不是FactoryBean,或者指定名称是FactoryBean引用,也就是普通的bean调用,则直接返回;
//如果我们有了个bean的实例,这个实例可能是bean可能是beanfactory,如果是FactoryBean我们使用它去创建实例,但是如果用户想要直接获取工厂实例而不是工厂的getObject方法所对应的实例,
//那么传入的name应该加前缀&
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
}
  • 3.以上情况都不是,则对FactoryBean调用getObjectFromFactoryBean()获取实例:
/**
	 * Obtain an object to expose from the given FactoryBean.
	 * @param factory the FactoryBean instance
	 * @param beanName the name of the bean
	 * @param shouldPostProcess whether the bean is subject to post-processing
	 * @return the object obtained from the FactoryBean
	 * @throws BeanCreationException if FactoryBean object creation failed
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		//如果是单例
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				//如果缓存中存在直接获取,不需要创建 反之创建
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					//获取实例
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

 

欢迎加入作者的微信公众号:

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值