`
lovnet
  • 浏览: 6718190 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

Spring FactoryBean源码浅析

 
阅读更多

在SpringBeanFactory容器中管理两种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的FactoryBean增强我们的目标对象.rar

    通过FactoryBean在获取目标类的时间我们将增强的代理类给返回,使得我们调用方法的时间使用的代理类来增强,如果需要继续使用未代理的对象,则直接@Autowired 注入使用.

    spring源码解析之FactoryBean相关测试代码demo

    spring源码解析之FactoryBean相关测试代码demo,文章中也有相关代码

    详解Spring中的FactoryBean

    本篇文章主要介绍了Spring中的FactoryBean,如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean

    spring中的FactoryBean代码示例

    主要介绍了spring中的FactoryBean代码示例,涉及FactoryBean的实现等相关内容,具有一定参考价值,需要的朋友可以了解下。

    spring中FactoryBean中的getObject()方法实例解析

    主要介绍了spring中FactoryBean中的getObject()方法实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

    SpringFactoryBean:spring FactoryBean的样本,在运行时在两个bean之间进行更改

    spring FactoryBean的小样本,如何在运行时在两个bean之间进行切换。

    Spring中的FactoryBean.rar

    Spring中的FactoryBean.rar

    简单了解Spring中BeanFactory与FactoryBean的区别

    主要介绍了简单了解Spring中BeanFactory与FactoryBean的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    spring aop 实现源代码--xml and annotation(带lib包)

    我们分别定义了一个MessageSender对象(messageSenderImpl)和一个Before Advice对象(logBeforeAdvice),并定义了一个 org.springframework.aop.framework.ProxyFactoryBean对象(messageSender),FactoryBean或...

    FactoryBean代码最简实现

    这篇代码主要适用于我的博客,用来帮助理解Spring配置文件+FactoryBean的实例化过程。注意,这里是FactoryBean,而不是BeanFactory,下载资源要看清楚哈。

    Spring中BeanFactory与FactoryBean接口的区别详解

    主要给大家介绍了关于Spring中BeanFactory与FactoryBean接口的区别的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

    深入了解Spring中的FactoryBean

    主要介绍了深入了解Spring中的FactoryBean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    spring如何通过FactoryBean配置Bean

    主要介绍了spring如何通过FactoryBean配置Bean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    Spring BeanFactory和FactoryBean区别解析

    主要介绍了Spring BeanFactory和FactoryBean区别解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    Spring基于ProxyFactoryBean创建AOP代理

    主要介绍了Spring基于ProxyFactoryBean创建AOP代理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    spring:这是Spring框架研究

    spring This is spring framework study ...八、使用spring FactoryBean技术模拟mybatis MapperScan注解 https://github.com/AvengerEug/spring/tree/develop/implement-mapperscan 九、mybatis源码学习 ...

    初探spring aop内部实现 java

    初探spring aop内部实现 、从源代码解读spring之DataSource实现和FactoryBean模式

    spring的详细介绍

    Spring介绍 1. Spring 2. 使用spring的主要目的 3. Spring的模块 Ejb容器(以前是) Ioc容器(现在的控制权) 控制反转Ioc(Invertion of control)依赖注入(Dependency Injection) ...13. 接口FactoryBean的使用

    spring4示例代码

    spring-2 演示了外部配置文件的引入(connection),spel(spring el)表达式 ,静态工厂方式及实例工厂方式及factorybean方式创建bean, spring的生命周期及BeanPostProcessor的使用,注解方式创建bean 及使用...

    factory-bean-demo.7z

    spring 自定义 FactoryBean 样例工程,可以通过这个工程通过实现FactoryBean来扩展Spring容器

Global site tag (gtag.js) - Google Analytics