FactoryBean接口

实现类对象将被用作创建Bean实例的工厂,即调用getObject()方法返回的对象才是真正要使用的Bean实例,而不是直接将FactoryBean对象作为暴露的Bean实例。

FactoryBeans可以支持singleton和prototype,并且可以根据需要懒加载或在启动时立即创建对象。

这个接口在编写扫描接口生成代理对象的场景下经常使用,比如Mybatis Mapper接口扫描、Dubbo接口扫描、Feign接口扫描等。

Spring容器只负责管理FactoryBean实例的生命周期,而不是FactoryBean创建的对象的生命周期。因此不会自动调用暴露的Bean对象的destroy方法。FactoryBean应该实现DisposableBean,并将关闭调用委托给底层对象。

public interface FactoryBean {/** * Return an instance (possibly shared or independent) of the object * managed by this factory. */T getObject() throws Exception;/** * Return the type of object that this FactoryBean creates, * or null if not known in advance. */Class getObjectType();/** * Is the object managed by this factory a singleton? */default boolean isSingleton() {return true;}}

我们可以使用正常的getBean(beanName)方式获取通过getObject()方法暴露的Bean实例,也可以使用getBean(“&” + beanName)方式获取FactoryBean的实例。

下文将介绍其实现方式。

FactoryBean的实现方式

Spring创建单例Bean的逻辑在DefaultListableBeanFactory的preInstantiateSingletons()方法中:

public void preInstantiateSingletons() throws BeansException {List beanNames = new ArrayList(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {// 此处使用"& + beanName"作为beanName创建FactoryBean实例Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {FactoryBean factory = (FactoryBean) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction) ((SmartFactoryBean) factory)::isEagerInit,getAccessControlContext());} else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}} else {getBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...// ...}public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}protected  T doGetBean(String name, Class requiredType, Object[] args, boolean typeCheckOnly)throws BeansException {// 此步骤将&符移除String beanName = transformedBeanName(name);Object bean;Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);} else {if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);} else if (args != null) {return (T) parentBeanFactory.getBean(nameToLookup, args);} else if (requiredType != null) {return parentBeanFactory.getBean(nameToLookup, requiredType);} else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between");}registerDependentBean(dep, beanName);try {getBean(dep);} catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}if (mbd.isSingleton()) {// getSingleton方法中会先从单例池查找Bean// 如果没有则会调用lambda中的createBean(beanName, mbd, args)创建Bean并将其注册到单例池// 所以此时放入单例池的是FactoryBean实例sharedInstance = getSingleton(beanName, () -> {try {// 此处的beanName参数是不带&符的字符串return createBean(beanName, mbd, args);} catch (BeansException ex) {destroySingleton(beanName);throw ex;}});// beanName参数是不带&符的字符串// name是原始的带&符的字符串// 该方法里面会判断name是否有&符,如果有直接返回FactoryBean实例// 如果没有&符会调用getObject()方法获取真正要暴露的Bean实例bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);} else if (mbd.isPrototype()) {Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);} finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);} else {String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean");}Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);} finally {afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);} catch (IllegalStateException ex) {throw new BeanCreationException(beanName, "", ex);}}} catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}return (T) bean;}protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {// 判断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 {// 从factoryBeanObjectCache池获取object = getCachedObjectForFactoryBean(beanName);}if (object == null) {// Return bean instance from factory.FactoryBean factory = (FactoryBean) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.if (mbd == null && containsBeanDefinition(beanName)) {mbd = getMergedLocalBeanDefinition(beanName);}boolean synthetic = (mbd != null && mbd.isSynthetic());// 调用getObject()方法获取真正要暴露的Bean实例并将其放入factoryBeanObjectCache池object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;}