Spring 源码梳理(五) FactoryBean与BeanFactory

原创 2016年08月31日 15:24:47

FactoryBean与BeanFactory

1.什么是FactoryBean,后缀是'Bean'证明本质上仍然是一个Bean,仍然要放入BeanFactory中,只是它实现了FactoryBean<T>接口;

2.特点:根据该Bean的id从BeanFactory中获取的实际上是getObject返回的对象,要获得该FactoryBean本身,获取时需要加上'&';

3.为什么要使用factoryBean? 由于继承这个接口之后可以从getObject中获取对象,所以可以对该Bean进行针对性的处理然后返回所需要的Bean,例如可以为Bean做代理。可以看这个例子,这个接口在Spring内部经常用到。

http://blog.csdn.net/linuu/article/details/50855446

4.针对面试会问到它与BeanFactory有什么区别,经过上面的分析,它们之间本来就不是一类概念。 FactoryBean是Bean的一种,它也是放入BeanFactory中进行管理的。现在我们想知道的是如果在App类中加入这个接口,会对之前文章分析的执行顺序产生什么影响。 示例如下:

App.java

package com.mycompany.app;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

public class App implements InitializingBean,FactoryBean<Object>
{
	private App(){
		System.out.println("App.App()");
	}
	private  String says="App";
    public String getSays() {
		return says;
	}
	public void setSays(String says) {
		this.says = says;
	}
	public void say(){
    	System.out.println("App.app():"+says);
    }
	
	/**
	 * 在构造函数和getset方法之后执行postProcessBeforeInitialization方法
	 */
	/*这个方法是InitializingBean在继承InitializingBean接口后,要实现的方法,顾名思义,是在
	 *属性设置之后进行一些操作*/
	public void afterPropertiesSet() throws Exception {
		System.out.println("App.afterPropertiesSet()");
	}
	/*这个方法是在Spring配置中通过init-method属性指定为该方法,然后才会执行,在afterPropertiesSet方法之后*/
	public void initMethod(){
		System.out.println("App.initMethod()");
	}
	/**
	 *在afterPropertiesSet和initMethod方法之后执行postProcessAfterInitialization方法
	 */
	
	/*FactoryBean测试*/
	public Object getObject() throws Exception {
		System.out.println("App.getObject()");
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("test", "GetObject");
		return map;
	}
	public Class<?> getObjectType() {
		return new HashMap().getClass();
	}
	public boolean isSingleton() {
		return true;
	}
	
}


BeanFactoryPostProcessorAppTest.java

package com.mycompany.app;

import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanFactoryPostProcessorAppTest {
	public static void main(String[] args) {
    	@SuppressWarnings("resource")
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SpringBean.xml"); 
        Map map = (Map)applicationContext.getBean("app");  
        System.out.println("BeanFactoryPostProcessorAppTest.main():"+map.get("test").toString());
	}

}

其他的几个类同上篇文章,不变。

然后开始分析,我们说可以用&id和id的方式从BeanFactory中获取分别获取到FactoryBean本身和getObject返回的对象。那么在BeanFactory中其究竟保存了哪些Bean。

1)首先

Bean的实例化是在refresh方法中的finishBeanFactoryInitialization中:


2)然后preInstantiateSingletons方法:


3)很清楚的看到,当Bean为FactoryBean时,会在beanName的前面加上'&', 我们再进入getBean方法:


看到这个带有'&'的name,然后把'&'去掉,赋值给beanName,接着


我们看到createBean这个方法实际上是创建bean,而所创建的Bean的名字就是BeanName,并没有'&'符号。后面的getObjectForBeanInstance的第一个参数就是名字为beanName的bean。 (所以说BeanFactory中保存的其实是没有'&'符号的,这和预加载的时候beanFactory中的beanName是一致的):


然后我们进入getObjectForBeanInstance方法:


这个时候传进来的name带有'&'符号, 而if语句中也说明了

A:如果句柄引用的是一般的bean,直接返回这个Bean句柄;  (适用情景:正常的getBean())

B:或者引用的是factoryBean,而且有'&',直接返回这个Bean句柄;  (适用情景:获得factoryBean本身,如getBean('&App'))

C:如果引用的是factoryBean,而且没有'&',继续下面的语句  (适用情景: 从ApplicationContext中getBean(),

BeanFactoryPostProcessorAppTest.java中的getBean("app"))

不允许存在引用一般的bean,而且有‘&’符号,上面一个if已经说明了这一点。

4)接着我们分析if之后的语句

前面我们看到2)的然后preInstantiateSingletons方法,整个BeanFactory中bean的初始化都在for循环中,遍历BeanFactory中BeanNames,而且是beanFactory都被加上了'&'符号,所以就不存在上面的情况C ,只有当我们从applicationContext中getBean的时候才会出现情况C,如上面BeanFactoryPostProcessorAppTest.java。

后面就可以猜到了,逐层进入getObjectFromFactoryBean方法:


最后执行的是这个Bean中的getObject方法,到此分析就结束了。

5)运行结果如下,和我们的分析一致


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

BeanFactory 与 FactoryBean的区别及FactoryBean详解

原文地址:http://blog.csdn.net/is_zhoufeng/article/details/38422549 首先要分辨BeanFactory 与 FactoryBean的区...
  • u014604403
  • u014604403
  • 2016年01月14日 10:37
  • 8730

理解spring中的BeanFactory和FactoryBean的区别与联系

首先,这俩都是个接口…实现 BeanFactory 接口的类表明此类事一个工厂,作用就是配置、新建、管理 各种Bean。而 实现 FactoryBean 的类表明此类也是一个Bean,类型为工厂Bea...
  • joenqc
  • joenqc
  • 2017年03月26日 20:51
  • 1018

Spring源码学习之BeanFactory和FactoryBean

今天在学习Spring源码的时候,发现了spring中不仅仅有BeanFactory,还有FactoryBean,突然觉得分不清这两者之间有什么不同,难道仅仅是名字吗?但是从名字上我们也能看出一些端倪...
  • hsj1213522415
  • hsj1213522415
  • 2017年02月24日 11:35
  • 206

spring中BeanFactory和FactoryBean的区别

spring中BeanFactory和FactoryBean的区别
  • qiesheng
  • qiesheng
  • 2017年06月06日 10:13
  • 1350

BeanFactory 和FactoryBean的区别

BeanFactory 和FactoryBean的区别 博客分类: Spring BeanSpringprototype  Spring的BeanFacotry是一个类工厂,使用它...
  • ccecwg
  • ccecwg
  • 2014年05月12日 16:16
  • 451

关于BeanFactory,FactoryBean,ObjectFactory

在看ObjectFactoryCreatingFactoryBean这个类的意思时,被FactoryBean,BeanFactory,ObjectFactory这几个接口弄的有点蒙。现在说一下这几个接...
  • hotdust
  • hotdust
  • 2016年10月10日 20:15
  • 888

Spring之FactoryBean

springAop的实现主要是通过动态代理技术。
  • is_zhoufeng
  • is_zhoufeng
  • 2014年08月07日 18:13
  • 30619

Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法

Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法 1. BeanFactory   BeanFactory,以Factory结尾,表示它是一个工厂...
  • yinbucheng
  • yinbucheng
  • 2017年03月23日 21:08
  • 342

Spring BeanFactory 与 FactoryBean的区别

BeanFactory: 以Factory结尾,表示它是一个工厂类,是用于管理Bean的一个工厂 FactoryBean:以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了Fac...
  • ggj20ss
  • ggj20ss
  • 2015年07月23日 17:11
  • 1094

Spring入门学习——使用Spring的FactoryBean创建Bean

有时候希望使用Spring的工厂Bean在Spring IoC容器中创建Bean。工厂Bean(Factory Bean)是作为创建IoC容器中其他Bean的工厂的一个Bean(拗口~)。工厂Bean...
  • QUITE_CGY
  • QUITE_CGY
  • 2017年04月21日 10:49
  • 707
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spring 源码梳理(五) FactoryBean与BeanFactory
举报原因:
原因补充:

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