Spring FactoryBean源码浅析

原创 2012年03月30日 14:39:48

在Spring BeanFactory容器中管理两种bean  

1.标准Java Bean  

2,另一种是工厂Bean,   即实现了FactoryBean接口的bean  它不是一个简单的Bean 而是一个生产或修饰对象生成的工厂Bean

在向Spring容器获得bean时  对于标准的java Bean  返回的是类自身的实例 

而FactoryBean 其返回的对象不一定是自身类的一个实例,返回的是该工厂Bean的getObject方法所返回的对象

一个简单的例子

public class SayHelloFactoryBeanImpl implements FactoryBean {

	/**
	 * 返回该工厂生成的bean
	 */
	public Object getObject() throws Exception {
		return new ChinaSayHelloServiceImpl();
	}

	/**
	 * getObject返回对象对应的Class
	 */
	public Class getObjectType() {
		return ChinaSayHelloServiceImpl.class;
	}
	
	/**
	 * getObject返回的对象 是否是一个单例
	 */
	public boolean isSingleton() {
		return false;
	}
}
配置文件
<bean id="sayHelloFactoryBean" class="com.xx.service.impl.SayHelloFactoryBeanImpl" />
		ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-server.xml"}, true);
		//bean的 getObject方法 返回的对象
		Object object = context.getBean("sayHelloFactoryBean");
		System.out.println(object);

控制台输出

com.xx.service.impl.ChinaSayHelloServiceImpl@1f66cff

容器返回的是 bean getObject方法返回对象  而不是SayHelloFactoryBeanImpl自身的实例 当然可以用“&”符号转义 获得FactoryBean的自身实例

ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-server.xml"}, true);
		//可以用转义符"&"来获得FactoryBean本身实例		
		System.out.println(context.getBean("&sayHelloFactoryBean"));

控制台输出

com.xx.service.impl.SayHelloFactoryBeanImpl@75e4fc

下面看看FactoryBean是怎么实现的

Spring  FactoryBean接口定义

public interface FactoryBean {

	Object getObject() throws Exception;

	Class getObjectType();

	boolean isSingleton();
}

bean的实例化 是在AbstractBeanFactory getBean方法发生的

public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
		return doGetBean(name, requiredType, args, false);
	}
protected Object doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
		// bean name处理  如果是以"&"开头  截取掉  
		final String beanName = transformedBeanName(name);
		Object bean = null;
		//单例的bean 只实例化一次  第一次实例化后会放到一个Map中 即singletonObjects map集合中  下次使用的时候直接拿
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			// FactoryBean 相关处理 在此方法发生
			//name 调用getBean时传入的参数 
			//beanName 截取"&"后的name
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			...略
		}
		return bean;
}
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
		// 如果不是FactoryBean的相关调用 结束处理
		//isFactoryDereference 方法判断name 是不是以"&"开始  如果以"&"开始 返回true
		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}
		Object object = null;
		//bean的定义为null
		if (mbd == null) {
			//缓存集合factoryBeanObjectCache中包含  当前bean getObject方法返回的实例  不需要在调用 直接返回
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			FactoryBean factory = (FactoryBean) beanInstance;
			//containsBeanDefinition方法->  bean的定义map beanDefinitionMap集合中 是否包含该bean的定义
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			// FactoryBean getObject触发   并缓存到factoryBeanObjectCache集合中
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
	protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
		//当前的factoryBean是否单例  并且  缓存singletonObjects‘Map中包含FactoryBean的自身实例
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				// factoryBeanObjectCache 缓存的是 getObject返回的对象
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					//getObject方法调用
					object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
					//缓存 getObject方法返回的实例对象
					this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
				}
				return (object != NULL_OBJECT ? object : null);
			}
		}
		else {
			//getObject方法调用
			return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
		}
	}
	private Object doGetObjectFromFactoryBean(
			final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
			throws BeanCreationException {
		AccessControlContext acc = AccessController.getContext();
		return AccessController.doPrivileged(new PrivilegedAction() {
			public Object run() {
				Object object;

				try {
					// getObject方法调用
					object = factory.getObject();
				}
				catch (FactoryBeanNotInitializedException ex) {
					throw new BeanCurrentlyInCreationException(beanName, ex.toString());
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
				}
				if (object == null && isSingletonCurrentlyInCreation(beanName)) {
					throw new BeanCurrentlyInCreationException(
							beanName, "FactoryBean which is currently in creation returned null from getObject");
				}

				if (object != null && shouldPostProcess) {
					try {
						object = postProcessObjectFromFactoryBean(object, beanName);
					}
					catch (Throwable ex) {
						throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
					}
				}

				return object;
			}
		}, acc);
	}

当一个受Spring容器管理的bean  如果实现了FactoryBean接口  在bean实例化(getBean)阶段  Spring会调用该bean的getObejct方法 返回的不一定是自身的实例

Spring 框架中有很多FactoryBean   例如RmiProxyFactoryBean, SqlMapClientFactoryBean. LocalSessionFactoryBean等都是通过FactoryBean getObject方法驱动起来的.对bean的生产 修饰做了很好的封装。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Spring 循环引用 ——理解singleton与prototype初始化的区别

spring的循环引用解决机制 以及singleton与prototype能否实现循环引用的原因。

浅谈spring中的Singleton

首先让我们看看一个Bean是怎么样通过Spring实例化的例子:action-servlet.xml  当singleton="true"的时候,这个属性使spring所做的是,通过缓冲使所有对这个B...
  • zoucui
  • zoucui
  • 2009年02月16日 21:49
  • 18386

FactoryBean的实现原理与作用

本文通过简单描述FactoryBean与Beanfactory的区别,通过IOC源码中对该类型的Bean的解析讲解其原理,并附上小案例帮助大家理解FactoryBean的核心方法。...

深入解读Spring Framework IoC容器(第五弹:懒加载)

懒加载也称延迟加载或延迟初始化。Spring默认在启动时将所有单例bean提前进行实例化,也就是说默认不是懒加载的。Ioc容器会把懒加载的bean在第一次需要的时候才实例化而不是在容器启动时就实例化。...

spring学习-FileSystemXmlApplicationContext与DefaultListableBeanFactory

FileSystemXmlApplicationContext的接口关系 一:基类AbstractApplicationContext继承DefaultResourceLoader,实现Confi...

做一个合格的程序猿之浅析Spring IoC源码(七)浅谈BeanFactory和FactoryBean

这次就不一句句翻译了(太多了),还是稍微大概的讲一下意思吧:FactoryBean是一个接口,任何一个Bean可以实现这个接口,那么这个bean将成为一个Factory,这个Factory将一些对象暴...
  • linuu
  • linuu
  • 2016年03月11日 13:37
  • 1061

Spring源码学习--FactoryBean实现原理

1、概述spring中有两种类型的Bean:一种是普通的JavaBean;另一种就是工厂Bean(FactoryBean),这两种Bean都受Spring的IoC容器管理,但它们之间却有一些区别。2、...

spring源码附录(4)FactoryBean的使用

一、FactoryBean接口public interface FactoryBean { T getObject() throws Exception; Class getObjectT...

做一个合格的程序猿之浅析Spring IoC源码(五)再谈BeanPostProcessor(2)

上一节,我们已经初步知道了beanPostProcessor这个接口是干什么的了,可以做什么样的事情,并且我们举了一个简单的“Teacher”的例子,但是大家也有点疑问,这个实际意义是什么呢?在项目中...
  • linuu
  • linuu
  • 2016年03月10日 15:55
  • 1037
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spring FactoryBean源码浅析
举报原因:
原因补充:

(最多只允许输入30个字)