Spring擴展點之FactoryBean接口

前言

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

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

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

Spring擴展點之FactoryBean接口

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技術的重點,簡單回顧一下吧

Spring擴展點之FactoryBean接口

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;
 }

我是小架,我們

下篇文章再見!


分享到:


相關文章: