http://blog.csdn.net/java2000_wl/article/details/7410714

在Spring BeanFactory容器中管理两种bean

1.标准Java Bean

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

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

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

一个简单的例子

  1. public class SayHelloFactoryBeanImpl implements FactoryBean {
  2. /**
  3. * 返回该工厂生成的bean
  4. */
  5. public Object getObject() throws Exception {
  6. return new ChinaSayHelloServiceImpl();
  7. }
  8. /**
  9. * getObject返回对象对应的Class
  10. */
  11. public Class getObjectType() {
  12. return ChinaSayHelloServiceImpl.class;
  13. }
  14. /**
  15. * getObject返回的对象 是否是一个单例
  16. */
  17. public boolean isSingleton() {
  18. return false;
  19. }
  20. }
  1. 配置文件
  2. <bean id="sayHelloFactoryBean" class="com.xx.service.impl.SayHelloFactoryBeanImpl" />
  1. ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:applicationContext-server.xml"}, true);
  2. //bean的 getObject方法 返回的对象
  3. Object object = context.getBean("sayHelloFactoryBean");
  4. System.out.println(object);

控制台输出

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

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

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

控制台输出

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

下面看看FactoryBean是怎么实现的

Spring  FactoryBean接口定义

  1. public interface FactoryBean {
  2. Object getObject() throws Exception;
  3. Class getObjectType();
  4. boolean isSingleton();
  5. }

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

  1. public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
  2. return doGetBean(name, requiredType, args, false);
  3. }
  1. protected Object doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
  2. // bean name处理  如果是以"&"开头  截取掉
  3. final String beanName = transformedBeanName(name);
  4. Object bean = null;
  5. //单例的bean 只实例化一次  第一次实例化后会放到一个Map中 即singletonObjects map集合中  下次使用的时候直接拿
  6. Object sharedInstance = getSingleton(beanName);
  7. if (sharedInstance != null && args == null) {
  8. // FactoryBean 相关处理 在此方法发生
  9. //name 调用getBean时传入的参数
  10. //beanName 截取"&"后的name
  11. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  12. }
  13. else {
  14. ...略
  15. }
  16. return bean;
  1. protected Object getObjectForBeanInstance(
  2. Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
  3. // 如果不是FactoryBean的相关调用 结束处理
  4. //isFactoryDereference 方法判断name 是不是以"&"开始  如果以"&"开始 返回true
  5. if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
  6. throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
  7. }
  8. if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
  9. return beanInstance;
  10. }
  11. Object object = null;
  12. //bean的定义为null
  13. if (mbd == null) {
  14. //缓存集合factoryBeanObjectCache中包含  当前bean getObject方法返回的实例  不需要在调用 直接返回
  15. object = getCachedObjectForFactoryBean(beanName);
  16. }
  17. if (object == null) {
  18. FactoryBean factory = (FactoryBean) beanInstance;
  19. //containsBeanDefinition方法->  bean的定义map beanDefinitionMap集合中 是否包含该bean的定义
  20. if (mbd == null && containsBeanDefinition(beanName)) {
  21. mbd = getMergedLocalBeanDefinition(beanName);
  22. }
  23. boolean synthetic = (mbd != null && mbd.isSynthetic());
  24. // FactoryBean getObject触发   并缓存到factoryBeanObjectCache集合中
  25. object = getObjectFromFactoryBean(factory, beanName, !synthetic);
  26. }
  27. return object;
  28. }
  1. protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
  2. //当前的factoryBean是否单例  并且  缓存singletonObjects‘Map中包含FactoryBean的自身实例
  3. if (factory.isSingleton() && containsSingleton(beanName)) {
  4. synchronized (getSingletonMutex()) {
  5. // factoryBeanObjectCache 缓存的是 getObject返回的对象
  6. Object object = this.factoryBeanObjectCache.get(beanName);
  7. if (object == null) {
  8. //getObject方法调用
  9. object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
  10. //缓存 getObject方法返回的实例对象
  11. this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
  12. }
  13. return (object != NULL_OBJECT ? object : null);
  14. }
  15. }
  16. else {
  17. //getObject方法调用
  18. return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
  19. }
  20. }
  1. private Object doGetObjectFromFactoryBean(
  2. final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
  3. throws BeanCreationException {
  4. AccessControlContext acc = AccessController.getContext();
  5. return AccessController.doPrivileged(new PrivilegedAction() {
  6. public Object run() {
  7. Object object;
  8. try {
  9. // getObject方法调用
  10. object = factory.getObject();
  11. }
  12. catch (FactoryBeanNotInitializedException ex) {
  13. throw new BeanCurrentlyInCreationException(beanName, ex.toString());
  14. }
  15. catch (Throwable ex) {
  16. throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
  17. }
  18. if (object == null && isSingletonCurrentlyInCreation(beanName)) {
  19. throw new BeanCurrentlyInCreationException(
  20. beanName, "FactoryBean which is currently in creation returned null from getObject");
  21. }
  22. if (object != null && shouldPostProcess) {
  23. try {
  24. object = postProcessObjectFromFactoryBean(object, beanName);
  25. }
  26. catch (Throwable ex) {
  27. throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
  28. }
  29. }
  30. return object;
  31. }
  32. }, acc);
  33. }

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

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

转:Spring FactoryBean源码浅析的更多相关文章

  1. spring初始化源码浅析之关键类和扩展接口

    目录 1.关键接口和类 1.1.关键类之 DefaultListableBeanFactory 1.2.关键类之XmlBeanDefinitionReader 1.3.关键类之ClassPathXml ...

  2. 【Spring】源码浅析 - ResponseEntity.ok 转载

    https://www.jianshu.com/p/1238bfb29ee1 ResponseEntity.ok具体源码

  3. Spring IOC 源码浅析

    控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心. 控制反转一般分为两种类型,依赖注入 ...

  4. spring源码浅析——IOC

    =========================================== 原文链接: spring源码浅析--IOC   转载请注明出处! ======================= ...

  5. 【原】Spring源码浅析系列-导入源码到Eclipse

    用了Spring几年,平时也断断续续在项目里看过一些源码,大多都是比较模糊的,因为一旦从一个地方进去就找不到方向了,只能知道它大概是做了什么事能达到这个功能或者效果,至于细节一般没有太深入去研究.后来 ...

  6. spring事务源码研读1

    转载摘录自:Spring事务源码分析(一)Spring事务入门 有时为了保证一些操作要么都成功,要么都失败,这就需要事务来保证. 传统的jdbc事务如下: @Test public void test ...

  7. Struts2源码浅析-ConfigurationProvider

    ConfigurationProvider接口 主要完成struts配置文件 加载 注册过程 ConfigurationProvider接口定义 public interface Configurat ...

  8. spring jdbcTemplate源码剖析

    本文浅析 spring jdbcTemplate 源码,主要是学习其设计精髓.模板模式.巧妙的回调 一.jdbcTemplate 类结构 ①.JdbcOperations : 接口定义了方法,如 &l ...

  9. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

随机推荐

  1. Cocos2dx 3.1.1 学习笔记整理(4):事件监听与Action的初步使用

    项目忙,趁着刚才有点空,看了下触摸事件在新版本中怎么实现,遇到问题都是去:cocos2d-x-3.1.1\tests\cpp-tests\Classes下面找的,里面都是一些小例子. 首先新的CCNo ...

  2. openstack controller ha测试环境搭建记录(三)——配置haproxy

    haproxy.cfg请备份再编辑:# vi /etc/haproxy/haproxy.cfg global    chroot /var/lib/haproxy    daemon    group ...

  3. [Unity Physics]Physics - Rigidbody、Collider

    什么是Collider 碰撞器组件在Unity引擎中触发物理碰撞的最基本的条件. 可以这样说,假如一个游戏中没有物理碰撞系统是不可能的. 什么是Rigidbody 通过物理模拟的控制对象的位置. Ri ...

  4. Kconfig基本语法

    Linux 内核在2.6版本以后将配置文件由原来的config.in改为Kconfig.当执行make menuconfig时会出现内核的配置界面,所有配置工具都是通过读取arch/$(ARCH)Kc ...

  5. 改变导航栏title字体的大小和颜色

    方法一:自定义视图的方法 就是在导航向上添加一个titleView,可以使用一个label,再设置label的背景颜色透明,字体什么的设置就很简单了. //自定义标题视图 UILabel *title ...

  6. jquery 改变变量出现值不同步

    出现问题的代码 var unc = 0; $.get( 'index.php', 'data=1', function(res) { unc=1; } ); alert(nuc); 这样的话,不管aj ...

  7. 设计模式笔记之一:MVP架构模式入门(转)

    写在前面:昨天晚上,公司请来专家讲解了下MVP,并要求今后各自负责的模块都要慢慢的转到MVP模式上来.以前由于能力有限,没有认真关注过设计模式.框架什么的,昨晚突然兴趣大发,故这两天空闲时间一直在学习 ...

  8. Word中的公式向上偏或向下偏的解决方法

    在word 2010中,发现公式无法与文字排成一行时,可选中文字,然后点“字体”,然后“高级”选项中选择“位置”,然后根据不同情况选择“标准”.“提升”.“降低”.

  9. 概率dp初探

    论文链接:  http://wenku.baidu.com/link?url=vEcfxpqAvGRf6JL9IL2R6v8plBgPnaP3tKp5niOBmoajk0y4CcpwFzL4SkfGS ...

  10. ARM处理器寄存器

    参考:ARM Architecture Reference Manual的39页 1.ARM处理器寄存器纵览 ARM微处理器共有37个32位寄存器,其中31个为通用寄存器(R13和R13_svc不是同 ...