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)运行结果如下,和我们的分析一致


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

相关文章推荐

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

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

Spring源码之ApplicationContext(五)激活BeanFactory

这一节我们主是看一个函数invokeBeanFactoryPostProcessors,在前面我们已经知道,这个函数的作用就是激活各种BeanFactory处理器。置于Spring的内部是怎么实现的,...

【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)

什么是IoC         IoC容器,最主要的就是完成对象的创建以及维护对象的依赖关系等。        所谓控制反转,包括两部分:一是控制,二是反转,就是把传统方式需要由代码来实现对象的创建...

Spring中的BeanFactory和FactoryBean的区别

1、 BeanFactory     BeanFactory定义了 IOC 容器的最基本形式,并提供了 IOC 容器应遵守的的最基本的接口,也就是Spring IOC 所遵守的最底层和...

【Spring】普通bean、FactoryBean、BeanFactory的区别与联系

在Spring中这三点比较容易混淆:一. FactoryBean、BeanFactory的区别其实这两点没有什么联系,只是命名上比较相似,所以常常被拿出来比较。BeanFactoryBeanFacto...

spring BeanFactory与FactoryBean

一、综述 本文比较了RMI,Hessian,Burlap,Httpinvoker,web service等5种通讯协议的在不同的数据结构和不同数据量时的传输性能。RMI是java语言本身提供的通讯协议...

spring中bean,factorybean与beanfactory

1. 普通Bean的创建spring 中的普通bean的创建是通过读取配置文件,将所有配置文件信息保存到beandefinition中,在使用getbean的时候通过反射创建实例,然后再将属性值填充。...

spring的beanFactory和factoryBean

org.springframework.beans及org.springframework.context包是Spring IoC容器的基础。BeanFactory提供的高级配置机制,使得管理任何性质...

底层解惑-spring的IOC相关接口:BeanFactory与FactoryBean

一、区别 BeanFactory是个 Factory ,也就是 IOC 容器或对象工厂; FactoryBean 是个 Bean,但是不是普通的bean,该bean是通过getobject()...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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