Spring bean加載2--FactoryBean情況處理


Spring bean加載2--FactoryBean情況處理

在Spring bean加載過程中,每次bean實例在返回前都會調用getObjectForBeanInstance來處理FactoryBean的情況.
這邊的FactoryBean,Spring設計用於新建復雜bean的,聯想下GOF設計模式的創建型,一樣的為了解決復雜的bean實例化過程.
其實這邊的FactoryBean就是一個factory method[gof定義的意圖:定義一個用於創建對象的接口,讓子類決定實例化哪個類.Factory Method使一個類的實例化延遲到其子類].

這邊的處理主要涉及3個方法,我們來看看3個方法各自的職責:

  1. getObjectForBeanInstance: 參數校驗之類的准備工作
  2. getObjectFromFactoryBean: 單例時,確保實例是全局唯一的
  3. doGetObjectFromFactoryBean: 實實在在的實例化

參數校驗之類的准備工作##

AbstractBeanFactory的getObjectForBeanInstance處理.

  1. 如果name制定要獲取FactoryBean本身實例,而beanInstance卻又不是FactoryBean,直接拋異常
  2. 如果不需要調用getObject實例化,直接返回實例
  3. 嘗試從緩存中獲取實例[FactoryBeanRegistrySupport負責]
  4. 准備beanDefinition,委托getObjectFromFactoryBean處理

單例時保障實例全局唯一##

FactoryBeanRegistrySupport的getObjectFromFactoryBean處理
FactoryBeanRegistrySupport負責FactoryBean相關的操作,並緩存FactoryBean的getObject實例化的bean.

  1. 判斷factory是單例,同時已經new好了(后面需要調用getObject獲取目標對象,這邊需要factory已經實例化)
  2. 單例時,先嘗試去緩存找;如果找不到或者不是單例,委托doGetObjectFromFactoryBean實例化一個
  3. 由於這樣新建就沒有機會調用BeanPostProcessor了,所以這邊直接調用其postProcessAfterInitialization[職責職責職責,AbstractAutowireCapableBeanFactory干的]
  4. 緩沖得到的實例

實例化,干活的##

FactoryBeanRegistrySupport的doGetObjectFromFactoryBean處理
這邊做的事很少,就是調用factoryBean的getObject,然后如果實例化得到的對象為空拋異常.

源碼摘要##

AbstractBeanFactory

/**
 * Get the object for the given bean instance, either the bean
 * instance itself or its created object in case of a FactoryBean.
 * 返回bean 實例的對象,可能是實例本身,也可能是FactoryBean新建的對象
 * @param beanInstance the shared bean instance
 * @param name name that may include factory dereference prefix
 * @param beanName the canonical bean name
 * @param mbd the merged bean definition
 * @return the object to expose for the bean
 */
protected Object getObjectForBeanInstance(
		Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

    // 如果想要獲取FactoryBean本身,那么beanInstance必須是FactoryBean的實例
	// Don't let calling code try to dereference the factory if the bean isn't a factory.
	if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
		throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
	}

    // 如果instance不是FactoryBean實例,或者想要獲取的就是FactoryBean實例,那么直接返回就好
	// Now we have the bean instance, which may be a normal bean or a FactoryBean.
	// If it's a FactoryBean, we use it to create a bean instance, unless the
	// caller actually wants a reference to the factory.
	if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
		return beanInstance;
	}

	Object object = null;
	if (mbd == null) {
        // 獲取緩存的實例
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) {
        // 緩存中沒有對象,那么從頭准備bean defition實例化一個
		// 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());
		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
	}
	return object;
}

FactoryBeanRegistrySupport

/**
 * Obtain an object to expose from the given FactoryBean, if available
 * in cached form. Quick check for minimal synchronization.
 * 獲取緩存的,通過FactoryBean暴露出來的對象
 * @param beanName the name of the bean
 * @return the object obtained from the FactoryBean,
 * or {@code null} if not available
 */
protected Object getCachedObjectForFactoryBean(String beanName) {
	Object object = this.factoryBeanObjectCache.get(beanName);
    // 類似<重構>中Introduce NUll Object,只是這邊的NULL_OBJECT是Object類型的,沒有解決Martin說的"不需要詢問對象類型,就可以直接調用行為的方法"
	return (object != NULL_OBJECT ? object : null);
}

/**
 * Obtain an object to expose from the given FactoryBean.
 * @param factory the FactoryBean instance
 * @param beanName the name of the bean
 * @param shouldPostProcess whether the bean is subject to post-processing
 * @return the object obtained from the FactoryBean
 * @throws BeanCreationException if FactoryBean object creation failed
 * @see org.springframework.beans.factory.FactoryBean#getObject()
 */
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // factory是單例的同時,還得已經被實例化(感覺這個檢驗怪怪的,沒想明白)
	if (factory.isSingleton() && containsSingleton(beanName)) {
		synchronized (getSingletonMutex()) {
			Object object = this.factoryBeanObjectCache.get(beanName);
			if (object == null) {
                // 緩存中找不到,就自己干吧,實例化
				object = doGetObjectFromFactoryBean(factory, beanName);
				// Only post-process and store if not put there already during getObject() call above
				// (e.g. because of circular reference processing triggered by custom getBean calls)
				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
				if (alreadyThere != null) {
					object = alreadyThere;
				}
				else {
					if (object != null && shouldPostProcess) {
						try {
                            // 外面BeanPostProcessor作用在factory上,沒有作用在實際想要的實例上,這邊補一個
                            // 也就是說,BeanPostProcessor的postProcessBeforeInitialization不會作用在FactoryBean上
							object = postProcessObjectFromFactoryBean(object, beanName);
						}
						catch (Throwable ex) {
							throw new BeanCreationException(beanName,
									"Post-processing of FactoryBean's singleton object failed", ex);
						}
					}
                    // 緩存
					this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
				}
			}
			return (object != NULL_OBJECT ? object : null);
		}
	}
	else {
		Object object = doGetObjectFromFactoryBean(factory, beanName);
		if (object != null && shouldPostProcess) {
			try {
				object = postProcessObjectFromFactoryBean(object, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
			}
		}
		return object;
	}
}

/**
 * Obtain an object to expose from the given FactoryBean.
 * @param factory the FactoryBean instance
 * @param beanName the name of the bean
 * @return the object obtained from the FactoryBean
 * @throws BeanCreationException if FactoryBean object creation failed
 * @see org.springframework.beans.factory.FactoryBean#getObject()
 */
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(new PrivilegedExceptionAction<Object>() {
					@Override
					public Object run() throws Exception {
							return 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 && isSingletonCurrentlyInCreation(beanName)) {
		throw new BeanCurrentlyInCreationException(
				beanName, "FactoryBean which is currently in creation returned null from getObject");
	}
	return object;
}
/**
 * Post-process the given object that has been obtained from the FactoryBean.
 * The resulting object will get exposed for bean references.
 * <p>The default implementation simply returns the given object as-is.
 * Subclasses may override this, for example, to apply post-processors.
 * @param object the object obtained from the FactoryBean.
 * @param beanName the name of the bean
 * @return the object to expose
 * @throws org.springframework.beans.BeansException if any post-processing failed
 */
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
	return object;
}

AbstractAutowireCapableBeanFactory

/**
 * Applies the {@code postProcessAfterInitialization} callback of all
 * registered BeanPostProcessors, giving them a chance to post-process the
 * object obtained from FactoryBeans (for example, to auto-proxy them).
 * @see #applyBeanPostProcessorsAfterInitialization
 */
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
	return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (result == null) {
			return result;
		}
	}
	return result;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM