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 通过中间层工具类SpringBeanFactoryUtils 实现service 注入

SpringBeanFactoryUtils  源代码: package com.common.common.util; import org.springframework.beans.Bean...

ibatis源码浅析- 初始化

以SqlMapClientBuilder类的buildSqlMapClient方法为初始化入口 初始化过程 主要包括 1. 初始化全局配置(sqlMapConfig文件) 事务 DataSource...

Spring源码学习-5.AOP原理分析

AOP是Aspect-Oriented Programming 面向切面编程的简称 在Spring AOP的实现中,使用的是java本身的语言特性,如java proxy代理类,拦截器技术来实现AOP...

Spring源码学习-5.ProxyFactoryBean实现与源代码分析

1.设计原理 proxyConfig 在这个继承关系中,ProxyConfig是最底层的类,这是一个数据基类,为子类提供配置属性 AdvisedSupport: 封装了AOP对通知和通知器的操作 ...

软件人员推荐书目(一) 大师篇

软件人员推荐书目(一) 大师篇  一、 科学哲学和管理哲学  【1】 "程序开发心理学"(The Psychology of Computer Programming : Silver Annive...

做一个合格的程序猿之浅析Spring AOP源码(十四) 分析ProxyFactoryBean

最基本的实现有三个,AspectJProxyFactory.java ,ProxyFactory.java ProxyFactoryBean这三个,他们的父类ProxyCreatorSupport只是...
  • linuu
  • linuu
  • 2016-03-24 15:20
  • 2834

spring factory-method和factory-bean 使用

配置工厂Bean 通常由应用程序直接使用new创建新的对象,为了将对象的创建和使用相分离,采用工厂模式,即应用程序将对象的创建及初始化职责交给工厂对象. 一般情况下,应用程序有自己的工厂对...

Spring源代码之bean的基本解析

先看这样一段儿代码:spring bean xml配置 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmln...

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

这次就不一句句翻译了(太多了),还是稍微大概的讲一下意思吧:FactoryBean是一个接口,任何一个Bean可以实现这个接口,那么这个bean将成为一个Factory,这个Factory将一些对象暴...
  • linuu
  • linuu
  • 2016-03-11 13:37
  • 927
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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