Spring扩展点之FactoryBean接口
前言
首先看一下接口定义
public interface FactoryBean<T> {
    /**
     * 返回对象实例
     */
    @Nullable
    T getObject() throws Exception;
    /**
     * 返回对象类型,
     */
    @Nullable
    Class<?> getObjectType();
    /**
     * 该工厂管理的对象是否为单例?
     */
    default boolean isSingleton() {
        return true;
    }
}
由接口定义可以看出来,实现这个接口的bean不是主要功能,getObject()创建的对象才是重点。那么在这我们就可以猜到了,可以是使用FactoryBean创建一些实例化过程比较复杂的bean
FactoryBean的注册
FactoryBean的处理逻辑在AbstractBeanFactory.doGetBean方法内
protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {
        //获取bean名称
        final String beanName = transformedBeanName(name);
        Object bean;
			  //省略部分内容
            //这里就是FactoryBean的相关处理,下面会展开说
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
			 //省略部分内容
        return (T) bean;
    }
看一下具体的逻辑,这里需要注意Spring关于bean的name有个潜规则,凡是以&开头的bean名称都默认为FactoryBean
protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
	  // 如果beanName以工厂引用&开头
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        // 如果name以&开头,而beanInstance不是FactoryBean类型,则抛异常
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }
    }
    // 如果beanInstance不是FactoryBean类型,则直接返回beanInstance
    // 或者name以&开头,也直接返回beanInstance,说明我们就想获取FactoryBean实例
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }
    Object object = null;
    if (mbd == null) {
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // 此时beanInstance是FactoryBean类型,而name又不是以&开头; 这是我们示例工程的情况,也是最普通、用的最多的情况
        // 将beanInstance强转成FactoryBean类型
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // 从缓存中获取我们需要的实例对象
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 调用FactoryBean的getObject方法创建我们需要的实例对象
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    //针对单例的处理
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                //通过factory.getObject获取
                object = doGetObjectFromFactoryBean(factory, beanName);
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
                    object = alreadyThere;
                }
                else {
                    if (shouldPostProcess) {
                        if (isSingletonCurrentlyInCreation(beanName)) {
                            // Temporarily return non-post-processed object, not storing it yet..
                            return object;
                        }
                        beforeSingletonCreation(beanName);
                        try {
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                    "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                        finally {
                            afterSingletonCreation(beanName);
                        }
                    }
                    if (containsSingleton(beanName)) {
                        //将获取到的对象放到factoryBeanObjectCache单例缓存map进行存储
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            return object;
        }
    }
    else {
        //非单例的处理,直接通过factory.getObejct获取,然后再返回给用户
        Object object = doGetObjectFromFactoryBean(factory, beanName);
        if (shouldPostProcess) {
            try {
                object = postProcessObjectFromFactoryBean(object, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
            }
        }
        return object;
    }
}
生成bean对象的方法:
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
      throws BeanCreationException {
   Object object;
   try {
      if (System.getSecurityManager() != null) {
         AccessControlContext acc = getAccessControlContext();
         try {
            object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
         }
         catch (PrivilegedActionException pae) {
            throw pae.getException();
         }
      }
      else {
         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);
   }
   // Do not accept a null value for a FactoryBean that's not fully
   // initialized yet: Many FactoryBeans just return null then.
   if (object == null) {
      if (isSingletonCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(
               beanName, "FactoryBean which is currently in creation returned null from getObject");
      }
      object = new NullBean();
   }
   return object;}
Spring的实现
Spring中实现这个接口的bean有很多,但是我们最熟悉也是最重要的就是在我之前文章中提到过得ProxyFactoryBean这个bean是实现AOP技术的重点,简单回顾一下吧

public Object getObject() throws BeansException {
		initializeAdvisorChain();
		if (isSingleton()) {
			return getSingletonInstance();
		}
		else {
			if (this.targetName == null) {
				logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
						"Enable prototype proxies by setting the 'targetName' property.");
			}
			return newPrototypeInstance();
		}
	}
private synchronized Object getSingletonInstance() {
		if (this.singletonInstance == null) {
			this.targetSource = freshTargetSource();
			if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
				// Rely on AOP infrastructure to tell us what interfaces to proxy.
				Class<?> targetClass = getTargetClass();
				if (targetClass == null) {
					throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
				}
				setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
			}
			// Initialize the shared singleton instance.
			super.setFrozen(this.freezeProxy);
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}
												
											Spring扩展点之FactoryBean接口的更多相关文章
- Spring扩展点之Aware接口族
		
引言 Spring中提供了各种Aware接口,方便从上下文中获取当前的运行环境,比较常见的几个子接口有:BeanFactoryAware,BeanNameAware,ApplicationContex ...
 - Spring扩展点-v5.3.9
		
Spring 扩展点 **本人博客网站 **IT小神 www.itxiaoshen.com 官网地址****:https://spring.io/projects/spring-framework T ...
 - Spring之BeanFactory和FactoryBean接口的区别
		
目录 一.BeanFactory接口 二.FactoryBean接口 1.简单实现 2.增强实现 3.FactoryBean的实际使用案例 三.总结 @ Spring框架中的BeanFactory ...
 - Spring扩展点之BeanPostProcessor
		
前言 BeanPostProcessor接口是Spring中一个非常重要的接口,它的接口定义如下 public interface BeanPostProcessor { Object postPro ...
 - Spring扩展点之BeanFactoryPostProcessor
		
前言 BeanFactoryPostProcessor接口是Spring中一个非常重要的接口,它的接口定义如下 public interface BeanFactoryPostProcessor { ...
 - spring扩展点之PropertyPlaceholderConfigurer
		
原理机制讲解 https://leokongwq.github.io/2016/12/28/spring-PropertyPlaceholderConfigurer.html 使用时多个配置讲解 ht ...
 - spring mvc 提供的几个常用的扩展点
		
转载 :http://blog.csdn.net/gufachongyang02/article/details/43836105 这是spring3 mvc的核心流程图: SpirngMVC的第 ...
 - Spring钩子方法和钩子接口的使用详解
		
本文转自:http://www.sohu.com/a/166804449_714863 前言 SpringFramework其实具有很高的扩展性,只是很少人喜欢挖掘那些扩展点,而且官方的Refrenc ...
 - Spring中的扩展点
		
Spring作为一个常用的IOC框架,在设计上预留了很多的扩展点,很多第三方开源框架,包括Spring自身也是基于这些扩展点实现的,这很好的体现了对修改关闭.对扩展开放的原则.总的来说Spring的扩 ...
 
随机推荐
- jenkins如何构建C#代码写的网站
			
纯粹是因为同事习惯了写C#代码,开发的网站用C#编译, 对于习惯了用Maven编译的测试人员,真是一头雾水.不用jenkins吧,效率特别低,每次收到开发发过来的版本,还要进行数据库相关配置,是非常累 ...
 - windows删除桌面右键“英特尔@显卡设置”
			
运行中输入:regedit 确认运行注册表编辑器,依次单击展开 HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers键 ...
 - Windows  |  Ubuntu 16.04/18.04 安装Pycharm并永久破解以及安装配置Anaconda3
			
Ubuntu 18.04下 1.安装python 2._版本,输入 sudo apt install python 命令行输入 python或python3会打开对应的版本. 输入 exit()或C ...
 - vue router 导航守卫生命周期
			
导航守卫 导航守卫主要用来通过跳转或取消的方式守卫导航.有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的.(记住参数或查询的改变并不会触发进入/离开的导航守卫.你可以通过观察$r ...
 - 201871010119-帖佼佼《面向对象程序设计(java)》第十七周学习总结
			
博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...
 - 精通awk系列
			
安装新版本gawk awk有很多种版本,例如nawk.gawk.gawk是GNU awk,它的功能很丰富. 本教程采用的是gawk 4.2.0版本,4.2.0版本的gawk是一个比较大的改版,新支持的 ...
 - (day47)jQuery
			
目录 一.初识jQuery (一)jQuery介绍 (二)版本介绍 (三)jQuery对象 (四)相关网站 (五)基础语法 二.查找标签 (一)基本选择器 (1)id选择器 (2)标签选择器 (3)c ...
 - VMware虚拟机安装使用及系统安装教程
			
虚拟机是利用软件来模拟出完整计算机系统的工具.具有完整硬件系统功能的.运行在一个完全隔离环境中.虚拟机的使用范围很广,如未知软件评测.运行可疑型工具等,即使这些程序中带有病毒,它能做到的只有破坏您的虚 ...
 - java为什么学JavaScript?
			
就现在的趋势来说,Spring无疑是一家独大的,它有太多利益 现在在Java EE开发中,Spring已经成为和Java核心库一样的基础设备,所以说假如想成为一个合格的Java程序员,Spring必定 ...
 - 13 opencv训练器
			
https://blog.csdn.net/WZZ18191171661/article/details/91305466 https://blog.csdn.net/qq_25352981/arti ...