Spring擴展點之FactoryBean接口

前言

我們首先來看一下接口的定義

public interface FactoryBean { /** * 返回對象實例 */ @Nullable T getObject() throws Exception; /** * 返回對象類型, */ @Nullable Class> getObjectType(); /** * 該工廠管理的對象是否為單例? */ default boolean isSingleton() { return true; } }

由接口定義可以看出來,實現這個接口的bean不是主要功能, getObject() 創建的對象才是重點。那麼在這我們就可以猜到了,可以是使用 FactoryBean 創建一些實例化過程比較複雜的bean

FactoryBean 的註冊

FactoryBean 的處理邏輯在 AbstractBeanFactory.doGetBean 方法內

protected T doGetBean( final String name, final Class 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) 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; }

我是小架,我們

下篇文章再見!