Spring FactoryBean

FactoryBean简介

在此之前我们说过BeanFactory,请千万不要将FactoryBeanBeanFactory 搞混了,毕竟他们有着天壤之别;

接口将由BeanFactory中使用的对象实现,这些对象本身就是单个对象的工厂。如果一个bean实现了这个接口, 它将被用作一个要公开的对象的工厂,而不是直接作为一个将要公开的bean实例。

注意:实现此接口的bean不能用作普通bean。FactoryBean是在bean样式中定义的, 但是为bean引用公开的对象(getObject())始终是它创建的对象。

FactoryBean可以支持 singletons prototypes,,并且可以根据需要缓慢地创建对象,或者在启动时急切地创建对象。 SmartFactoryBean接口允许公开更细粒度的行为元数据。

该接口在框架本身中大量使用,例如用于AOP ProxyFactoryBean或JndiObjectFactoryBean。它也可以用于自定义组件; 但是,这只在基础结构代码中常见。

FactoryBean是一个程序化的契约。实现不应该依赖注释驱动的注入或其他反射工具。getObjectType()getObject() 调用可能在引导过程的早期到达,甚至在任何后处理器设置之前。如果需要访问其他bean,请实现BeanFactoryAware并以编程方式获取它们。

容器只负责管理FactoryBean实例的生命周期,而不负责由FactoryBean创建的对象的生命周期。 因此,对公开的bean对象(如关闭。关闭不会自动调用()。相反, FactoryBean应该实现DisposableBean并将任何这样的close调用委托给底层对象。

最后,FactoryBean对象参与包含BeanFactory的bean创建同步。通常不需要内部同步, 除了为了在FactoryBean本身(或类似的)中进行延迟初始化。

FactoryBean与BeanFactory区别

BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。 在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。 但对FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean, 它的实现与设计模式中的工厂模式和修饰器模式类似

FactoryBean源码

public interface FactoryBean<T> {
    String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
    //返回此工厂管理的对象的实例(可能是共享的或独立的)。
    //与一样BeanFactory,这允许同时支持Singleton和Prototype设计模式。
    //如果在调用时尚未完全初始化此FactoryBean(例如,因为它包含在循环引用中),则抛出一个FactoryBeanNotInitializedException。
	T getObject() throws Exception;
    //返回此FactoryBean创建的对象的类型
    //这样一来,无需实例化对象即可检查特定类型的bean,例如在自动装配时。
    //对于创建单例对象的实现,此方法应尽量避免创建单例。它应该提前估计类型。对于原型,建议在此处返回有意义的类型。
    //可以在完全初始化此FactoryBean 之前调用此方法。它一定不能依赖初始化期间创建的状态。当然,如果可用,它仍然可以使用这种状态。
    //注意:自动装配将仅忽略返回null此处的FactoryBean 。因此,强烈建议使用FactoryBean的当前状态正确实现此方法。
	Class<?> getObjectType();
    //该工厂管理的对象是单例吗?也就是说,将getObject()始终返回相同的对象
    //如果FactoryBean指示保留单个对象,则从其返回的对象getObject()可能会被拥有的BeanFactory缓存。
    // 因此,true 除非FactoryBean始终公开相同的引用,否则不要返回。
    //FactoryBean本身的单例状态通常由拥有的BeanFactory提供;通常,它必须在那里定义为单例。
    //注意:此方法返回false不一定表示返回的对象是独立的实例。
    // 扩展SmartFactoryBean接口的实现可以通过其SmartFactoryBean.isPrototype()方法显式指示独立的实例 。
    // FactoryBean 不实现这个扩展接口的实现,简单地认为总是返回如果独立实例 isSingleton()实现返回false。
    //默认实现返回true,因为 FactoryBean通常会管理一个单例实例
	default boolean isSingleton() {
		return true;
	}
}

FactoryBean应用

这里我们用到了InitializingBean,您也可以不用的,直接 new 返回即可 详细的源代码FactoryBeanLearn.java

@Configuration
public class FactoryBeanLearn implements FactoryBean<BaseBean>,InitializingBean {

    Logger log  = LoggerFactory.getLogger(FactoryBeanLearn.class);

    private BaseBean baseBean;

    private final CustomConfigurationProperties customConfigurationProperties;

    public FactoryBeanLearn(CustomConfigurationProperties customConfigurationProperties) {
        this.customConfigurationProperties = customConfigurationProperties;
        log.info("customConfigurationProperties init : {}",customConfigurationProperties.toString());
    }

    @Override
    public BaseBean getObject() throws Exception {
        if(Objects.isNull(baseBean)){
            this.afterPropertiesSet();
        }
        return this.baseBean;
    }

    @Override
    public Class<?> getObjectType() {
        return BaseBean.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("实例化 FactoryBeanLearn");
        this.baseBean = this.buildBaseBean();
    }

    /**
     * <p>
     *       实例化对象
     * </p>
     * @param
     * @return BaseBean
     */
    private BaseBean buildBaseBean() {
        if (Objects.isNull(customConfigurationProperties)){
            throw new RuntimeException("customConfigurationProperties is null");
        }
        return BaseBean.builder()
                .beanId(customConfigurationProperties.getGender())
                .beanName(customConfigurationProperties.getAuthor()).build();
    }

}

FactoryBean在Spring中的应该

这里需要您对SpringIoc源码有一些了解,若还不了解,请先阅读一下几篇文章,会对接下来的阅读有所帮助

接下的分析来自 refresh() -> finishBeanFactoryInitialization(beanFactory); - >preInstantiateSingletons()

@Override
public void preInstantiateSingletons() throws BeansException {
	if (logger.isTraceEnabled()) {
		logger.trace("Pre-instantiating singletons in " + this);
	}
    //迭代一个副本,允许init方法注册新的bean定义。
    //this.beanDefinitionNames 保存了所有的 beanNames
	List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
	// 触发所有非延迟单例bean的初始化
	for (String beanName : beanNames) {
        //返回合并的RootBeanDefinition,遍历父bean定义
        //如果指定的bean对应于子bean定义。
        //这里其实也是一个重点,这里会有很多关于bean的类,后期我们会针对bean的类图进行讲解
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            //在此处会根据beanName判断bean是不是一个FactoryBean,实现了FactoryBean接口的bean,会返回true
			if (isFactoryBean(beanName)) {
                // 然后通过getBean()方法去获取或者创建单例对象
                // 注意:在此处为beanName拼接了一个前缀:FACTORY_BEAN_PREFIX
                // FACTORY_BEAN_PREFIX是一个常量字符串,即:&
                // 所以在此时容器启动阶段,对于factoryBeanLearn,应该是:getBean("&factoryBeanLearn")
				Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
				if (bean instanceof FactoryBean) {
					final FactoryBean<?> factory = (FactoryBean<?>) bean;
					boolean isEagerInit;
                    //判断是否需要在容器启动阶段,就去实例化getObject()返回的对象,即是否调用FactoryBean的getObject()方法
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
										((SmartFactoryBean<?>) factory)::isEagerInit,
								getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
					    //重点方法
                        //返回指定bean的一个实例,该实例可以是共享的,也可以是独立的。
						getBean(beanName);
					}
				}
			}
			else {
				getBean(beanName);
			}
		}
	}
	// 为所有适用的bean触发初始化后回调
    // 到这里说明所有的非懒加载的 singleton beans 已经完成了初始化
    // 如果我们定义的 bean 是实现了 SmartInitializingSingleton 接口的,那么在这里得到回调,忽略
	for (String beanName : beanNames) {
		Object singletonInstance = getSingleton(beanName);
		if (singletonInstance instanceof SmartInitializingSingleton) {
			final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
					smartSingleton.afterSingletonsInstantiated();
					return null;
				}, getAccessControlContext());
			}
			else {
				smartSingleton.afterSingletonsInstantiated();
			}
		}
	}
}
  • 在容器启动阶段,会先通过getBean()方法来创建FactoryBeanLearn的实例对象。如果实现了SmartFactoryBean接口, 且isEagerInit()方法返回的是true,那么在容器启动阶段,就会调用getObject()方法, 向容器中注册getObject()方法返回值的对象。否则,只有当第一次获取getObject()返回值的对象时,才会去回调getObject()方法。

  • 在getBean()中会调用到doGetBean()方法,下面为doGetBean()精简后的源码。从源码中我们发现,最终都会调用getObjectForBeanInstance()方法。

  • getObjectForBeanInstance

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// 如果不是一个 FactoryBean,则直接返回 
		// 如果是FactoryBean,且name是以&符号开头,那么表示的是获取FactoryBean的原生对象,也会直接返回
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
		    //从缓存中获取。什么时候放入缓存的呢?在第一次调用getObject()方法时,会将返回值放入到缓存。
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// 缓存从FactoryBean获取的对象(如果它是单例对象)
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
            //在getObjectFromFactoryBean()方法中最终会调用到getObject()方法
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
  • getObjectFromFactoryBean

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
	// 如果BeanFactory的isSingleton()方法返回值是true,表示getObject()返回值对象是单例的
	if (factory.isSingleton() && containsSingleton(beanName)) {
		synchronized (getSingletonMutex()) {
			// 再一次判断缓存中是否存在。(双重检测机制,和平时写线程安全的代码类似)
			Object object = this.factoryBeanObjectCache.get(beanName);
			if (object == null) {
				// 在doGetObjectFromFactoryBean()中才是真正调用getObject()方法
				object = doGetObjectFromFactoryBean(factory, beanName);
				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
				if (alreadyThere != null) {
					object = alreadyThere;
				}
				else {
					// 下面是进行后置处理,和普通的bean的后置处理没有任何区别
					if (shouldPostProcess) {
						if (isSingletonCurrentlyInCreation(beanName)) {
							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)) {
						this.factoryBeanObjectCache.put(beanName, object);
					}
				}
			}
			return object;
		}
	}
	//非单例
	else {
		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;
	}
}
  • doGetObjectFromFactoryBean

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 {//直接调用 FactoryBean 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);
	}
    //对于不完全的FactoryBean,不要接受空值
    //已初始化:许多factorybean只返回null。
	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;
}

Last updated