首頁 > 軟體

Spring BeanFactory工廠使用教學

2023-11-01 18:00:37

首先,我們想要知道一個介面有哪些功能,就必須要看這個介面的原始碼,在idea中,選中這個介面Ctrl+F12,來檢視這個介面裡面有哪些方法:

表面上來看,功能其實很少,檢視原始碼及其方法、功能

package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
public interface BeanFactory {
    // factoryBean 的跳脫識別符號。
	String FACTORY_BEAN_PREFIX = "&";
    // 根據 name 從容器中拿對應的 bean。
	Object getBean(String name) throws BeansException;
    // 根據 name 和 type 從容器中拿對應的 bean,要對 bean 的型別做校驗。
	<T> T getBean(String name, Class<T> requiredType) throws BeansException;
    // 在容器中能否找到與 name 匹配的 bean 或者 beanDefinition。
	boolean containsBean(String name);
	// 判斷 name 對對應的 bean 是不是 單例。
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
	// 判斷 name 對應的 bean 與指定的型別是否匹配。
	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws 
     NoSuchBeanDefinitionException;
	boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws 
       NoSuchBeanDefinitionException;
	//根據 name 獲取對應的 bean 的型別。
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    // 根據 name 獲取對應 bean 的 別名。
	String[] getAliases(String name);
}

BeanFactory表面上來看只有 getBean有點用,實際上我們不能只光看它介面,還要看它的實現類,實際上控制反轉、基本的依賴注入、直至 Bean 的生命週期的各種功能,都由它的實現類提供

  • HierarchicalBeanFactory:提供父容器的存取功能
  • ListableBeanFactory:提供了批次獲取Bean的方法
  • AutowireCapableBeanFactory:在BeanFactory基礎上實現對已存在範例的管理
  • ConfigurableBeanFactory:主要單例bean的註冊,生成範例,以及統計單例bean
  • ConfigurableListableBeanFactory:繼承了上述的所有介面,增加了其他功能:比如類載入器,型別轉化,屬性編輯器,BeanPostProcessor,作用域,bean定義,處理bean依賴關係, bean如何銷燬…
  • 實現類DefaultListableBeanFactory:實現了ConfigurableListableBeanFactory,註冊BeanDefinition,實現上述BeanFactory所有功能

來看一下DefaultListableBeanFactory的繼承關係圖:

可以看到,BeanFactory只是它實現的很少一部分,除了BeanFactory提供的getBean,還有其他方法,所以我們不能光看一個介面,還要看它的具體實現類

在這裡我們就只看它的DefaultSingletonBeanRegistry介面中的單例物件,這個為大家比較熟悉的,來看原始碼:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	/** Maximum number of suppressed exceptions to preserve. */
	/**
	 * 抑制異常數量最大值
	 */
	private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;
	/** Cache of singleton objects: bean name to bean instance. */
	/**
	 * 一級快取 這個就是我們大名鼎鼎的單例快取池 用於儲存我們所有的單範例bean
	 */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
	/** Cache of singleton factories: bean name to ObjectFactory. */
	/**
	 * 三級快取 該map使用者快取 key為 beanName  value 為ObjectFactory(包裝為早期物件)
	 */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
	/** Cache of early singleton objects: bean name to bean instance. */
	/**
	 * 二級快取 ,使用者快取我們的key為beanName value是我們的早期物件(物件屬性還沒有來得及進行賦值)
	 */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
	/** Set of registered singletons, containing the bean names in registration order. */
	/**
	 * 已註冊的單例名稱set
	 */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
	/** Names of beans that are currently in creation. */
	/**
	 * 該集合用於快取當前正在建立bean的名稱
	 */
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));
	/** Names of beans currently excluded from in creation checks. */
	/**
	 * 排除當前建立檢查的
	 */
	private final Set<String> inCreationCheckExclusions =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));
	/**
	 * Collection of suppressed Exceptions, available for associating related causes.
	 */
	@Nullable
	/**抑制異常的集合,可用於關聯相關原因*/
	private Set<Exception> suppressedExceptions;
	/** Flag that indicates whether we're currently within destroySingletons. */
	/**
	 * 指示我們當前是否在 destroySingletons 中的標誌。
	 */
	private boolean singletonsCurrentlyInDestruction = false;
	/** Disposable bean instances: bean name to disposable instance. */
	/**
	 * 用於快取記錄實現了DisposableBean 介面的範例
	 */
	private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
	/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
	/**
	 * 快取bean的屬性關係的對映<service,<aDao,bDa>>
	 */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
	/** Map between dependent bean names: bean name to Set of dependent bean names. */
	/**
	 * 儲存的是依賴 beanName 之間的對映關係:beanName - > 依賴 beanName 的集合
	 */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
	/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
	/**
	 * 儲存的是依賴 beanName 之間的對映關係:依賴 beanName - > beanName 的集合
	 */
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
	/**
	 * 註冊單例Bean
	 *
	 * @param beanName        the name of the bean
	 * @param singletonObject the existing singleton object
	 * @throws IllegalStateException
	 */
	@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		//斷言beanName是否為空
		Assert.notNull(beanName, "Bean name must not be null");
		//斷言singletonObject是否為空
		Assert.notNull(singletonObject, "Singleton object must not be null");
		synchronized (this.singletonObjects) {
			//從一級快取中通過beanName拿取Bean
			Object oldObject = this.singletonObjects.get(beanName);
			//一級快取中存在了,丟擲IllegalStateException
			if (oldObject != null) {
				throw new IllegalStateException("Could not register object [" + singletonObject +
						"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
			}
			//如果不存在,將singletonObject新增到一級快取
			addSingleton(beanName, singletonObject);
		}
	}
	/**
	 * Add the given singleton object to the singleton cache of this factory.
	 * <p>To be called for eager registration of singletons.
	 * 把物件加入到單例快取池中(所謂的一級快取 並且考慮迴圈依賴和正常情況下,移除二三級快取)
	 *
	 * @param beanName        the name of the bean
	 * @param singletonObject the singleton object
	 */
	protected void addSingleton(String beanName, Object singletonObject) {
		synchronized (this.singletonObjects) {
			//將singletonObject新增到一級快取中,同時移除二級、三級快取、並標記當前Bean已註冊
			this.singletonObjects.put(beanName, singletonObject);
			//移除三級快取
			this.singletonFactories.remove(beanName);
			//移除二級快取
			this.earlySingletonObjects.remove(beanName);
			//標記當前Bean已被註冊
			this.registeredSingletons.add(beanName);
		}
	}
	/**
	 * Add the given singleton factory for building the specified singleton
	 * if necessary.
	 * <p>To be called for eager registration of singletons, e.g. to be able to
	 * resolve circular references.
	 * 該方法用於把早期物件包裝成一個ObjectFactory 暴露到三級快取中 用於將解決迴圈依賴...
	 *
	 * @param beanName         the name of the bean
	 * @param singletonFactory the factory for the singleton object
	 */
	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		//斷言singletonFactory不為空
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		//同步加鎖
		synchronized (this.singletonObjects) {
			//單例快取池中沒有包含當前的bean
			if (!this.singletonObjects.containsKey(beanName)) {
				//加入到三級快取中,,,,,暴露早期物件用於解決迴圈依賴
				this.singletonFactories.put(beanName, singletonFactory);
				//從二級快取中移除
				this.earlySingletonObjects.remove(beanName);
				//標記當前Bean已經被註冊過
				this.registeredSingletons.add(beanName);
			}
		}
	}
	/**
	 * 該方法是一個空殼方法
	 *
	 * @param beanName the name of the bean to look for
	 * @return 快取中的物件(有可能是一個單例完整物件, 也有可能是一個早期物件 ( 用於解決迴圈依賴))
	 */
	@Override
	@Nullable
	public Object getSingleton(String beanName) {
		//在這裡 系統一般是允許早期物件參照的 allowEarlyReference通過這個引數可以控制解決迴圈依賴
		return getSingleton(beanName, true);
	}
	/**
	 * 在網上很多很多寫原始碼的大佬或者是<spring原始碼深度解析>一書上,也沒有說清楚為啥要使用三級快取(二級快取可不可以能夠
	 * 解決) 答案是:可以, 但是沒有很好的擴充套件性為啥這麼說.......
	 * 原因: 獲取三級快取-----getEarlyBeanReference()經過一系列的後置處理來給我們早期物件進行特殊化處理
	 * //從三級快取中獲取包裝物件的時候 ,他會經過一次後置處理器的處理對我們早期物件的bean進行
	 * 特殊化處理,但是spring的原生後置處理器沒有經過處理,而是留給了我們程式設計師進行擴充套件
	 * singletonObject = singletonFactory.getObject();
	 * 把三級快取移植到二級快取中
	 * this.earlySingletonObjects.put(beanName, singletonObject);
	 * //刪除三級快取中的之
	 * this.singletonFactories.remove(beanName);
	 *
	 * @param beanName            bean的名稱
	 * @param allowEarlyReference 是否允許暴露早期物件  通過該引數可以控制是否能夠解決迴圈依賴的.
	 * @return 這裡可能返回一個null(IOC容器載入單範例bean的時候,第一次進來是返回null)
	 * 也有可能返回一個單例物件(IOC容器載入了單範例了,第二次來獲取當前的Bean)
	 * 也可能返回一個早期物件(用於解決迴圈依賴問題)
	 */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		/**
		 * 第一步:我們嘗試去一級快取(單例快取池中去獲取物件,一般情況從該map中獲取的物件是直接可以使用的)
		 * IOC容器初始化載入單範例bean的時候第一次進來的時候 該map中一般返回空
		 */
		Object singletonObject = this.singletonObjects.get(beanName);
		//如果一級快取為空,並且標記正在建立
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			/**
			 * 嘗試去二級快取中獲取物件(二級快取中的物件是一個早期物件)
			 * 何為早期物件:就是bean剛剛呼叫了構造方法,還來不及給bean的屬性進行賦值的物件(純淨態)
			 * 就是早期物件
			 */
			singletonObject = this.earlySingletonObjects.get(beanName);
			/**
			 * 二級快取中也沒有獲取到物件,allowEarlyReference為true(引數是有上一個方法傳遞進來的true)
			 */
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					/**
					 * 再次嘗試從一級快取中去拿,如果還是沒拿到則嘗試去二級快取中拿
					 */
					singletonObject = this.singletonObjects.get(beanName);
					//一級快取中沒拿到
					if (singletonObject == null) {
						//嘗試從二級快取中去拿
						singletonObject = this.earlySingletonObjects.get(beanName);
						//二級快取還是空
						if (singletonObject == null) {
							/**
							 * 直接從三級快取中獲取 ObjectFactory物件 這個對接就是用來解決迴圈依賴的關鍵所在
							 * 在ioc後期的過程中,當bean呼叫了構造方法的時候,把早期物件包裹成一個ObjectFactory
							 * 暴露到三級快取中
							 */
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							//三級快取中獲取的物件不為空
							if (singletonFactory != null) {
								/**
								 * 在這裡通過暴露的ObjectFactory 包裝物件中,通過呼叫他的getObject()來獲取我們的早期物件
								 * 在這個環節中會呼叫到 getEarlyBeanReference()來進行後置處理
								 */
								singletonObject = singletonFactory.getObject();
								//把早期物件放置在二級快取,
								this.earlySingletonObjects.put(beanName, singletonObject);
								//ObjectFactory 包裝物件從三級快取中刪除掉
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		//返回這個Bean
		return singletonObject;
	}
	/**
	 * Return the (raw) singleton object registered under the given name,
	 * creating and registering a new one if none registered yet.
	 * 獲取單例物件(該流程用於觸發構建bean)
	 *
	 * @param beanName         the name of the bean
	 * @param singletonFactory the ObjectFactory to lazily create the singleton
	 *                         with, if necessary
	 * @return the registered singleton object
	 */
	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		//斷言beanName不為空
		Assert.notNull(beanName, "Bean name must not be null");
		//同步加鎖
		synchronized (this.singletonObjects) {
			//嘗試從一級快取池中獲取物件
			Object singletonObject = this.singletonObjects.get(beanName);
			//從一級快取中沒拿到
			if (singletonObject == null) {
				//當前是否是正在銷燬,是的話丟擲BeanCreationNotAllowedException異常
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
									"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				//判斷是否已啟用Debug偵錯模式
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				/**
				 * 標記當前的bean馬上就要被建立了
				 * singletonsCurrentlyInCreation 在這裡會把beanName加入進來,若第二次迴圈依賴(構造器注入會丟擲異常)
				 */
				beforeSingletonCreation(beanName);
				//標記是否為新建立的單例Bean
				boolean newSingleton = false;
				//標記是否記錄抑制異常
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				//如果為空,建立抑制異常集合
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 初始化 bean
					// 這個過程其實是呼叫 createBean() 方法
					singletonObject = singletonFactory.getObject();
					//標記這個Bean是新建立的
					newSingleton = true;
				} catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					//
					//在此期間是否隱式建立了單例物件 -> 如果是,則繼續處理它,因為異常指該狀態。
					singletonObject = this.singletonObjects.get(beanName);
					//一級快取中沒有,丟擲異常
					if (singletonObject == null) {
						throw ex;
					}
				} catch (BeanCreationException ex) {
					//記錄抑制異常
					if (recordSuppressedExceptions) {
						//遍歷抑制異常集合,新增相關原因
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				} finally {
					//記錄抑制異常集合置空,複用
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					//後置處理
					//主要做的事情就是把singletonsCurrentlyInCreation標記正在建立的bean從集合中移除
					afterSingletonCreation(beanName);
				}
				//是新建的單例Bean,新增到一級快取中去
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			//返回單例Bean
			return singletonObject;
		}
	}
	/**
	 * Register an exception that happened to get suppressed during the creation of a
	 * singleton bean instance, e.g. a temporary circular reference resolution problem.
	 * <p>The default implementation preserves any given exception in this registry's
	 * collection of suppressed exceptions, up to a limit of 100 exceptions, adding
	 * them as related causes to an eventual top-level {@link BeanCreationException}.
	 * 註冊在建立單例 bean 範例期間碰巧被抑制的異常,例如一個臨時的迴圈參照解析問題。
	 *
	 * @param ex the Exception to register
	 * @see BeanCreationException#getRelatedCauses()
	 */
	protected void onSuppressedException(Exception ex) {
		synchronized (this.singletonObjects) {
			//抑制異常集合不為空,且小於SUPPRESSED_EXCEPTIONS_LIMIT最大限制
			if (this.suppressedExceptions != null && this.suppressedExceptions.size() < SUPPRESSED_EXCEPTIONS_LIMIT) {
				//向抑制集合中新增異常
				this.suppressedExceptions.add(ex);
			}
		}
	}
	/**
	 * Remove the bean with the given name from the singleton cache of this factory,
	 * to be able to clean up eager registration of a singleton if creation failed.
	 * 從該工廠的單例快取中刪除bean ,以便能夠在建立失敗時清除單例的急切註冊。
	 *
	 * @param beanName the name of the bean
	 * @see #getSingletonMutex()
	 */
	protected void removeSingleton(String beanName) {
		//同步加鎖
		synchronized (this.singletonObjects) {
			//從一級快取中移除
			this.singletonObjects.remove(beanName);
			//從三級快取中移除
			this.singletonFactories.remove(beanName);
			//從二級快取中移除
			this.earlySingletonObjects.remove(beanName);
			//從Bean註冊標記集合中移除
			this.registeredSingletons.remove(beanName);
		}
	}
	/**
	 * 一級快取中是否存在該Bean
	 *
	 * @param beanName the name of the bean to look for
	 * @return
	 */
	@Override
	public boolean containsSingleton(String beanName) {
		//判斷一級快取中是否存在該Bean
		return this.singletonObjects.containsKey(beanName);
	}
	/**
	 * 獲取已註冊的單例Bean名字的集合
	 *
	 * @return
	 */
	@Override
	public String[] getSingletonNames() {
		synchronized (this.singletonObjects) {
			//獲取已註冊的單例Bean名字的集合
			return StringUtils.toStringArray(this.registeredSingletons);
		}
	}
	/**
	 * 獲取已註冊單例Bean範例的個數
	 *
	 * @return
	 */
	@Override
	public int getSingletonCount() {
		synchronized (this.singletonObjects) {
			//獲取已註冊單例Bean範例的個數
			return this.registeredSingletons.size();
		}
	}
	/**
	 * 標記當前Bean正在建立,主要解決迴圈依賴
	 *
	 * @param beanName   Bean名字
	 * @param inCreation 是否已標記
	 */
	public void setCurrentlyInCreation(String beanName, boolean inCreation) {
		//斷言Bean不為空
		Assert.notNull(beanName, "Bean name must not be null");
		//如果未標記,將beanName加到inCreationCheckExclusions集合中,已標記則移除
		if (!inCreation) {
			this.inCreationCheckExclusions.add(beanName);
		} else {
			this.inCreationCheckExclusions.remove(beanName);
		}
	}
	/**
	 * 返回當前Bean是否是正在建立
	 *
	 * @param beanName
	 * @return
	 */
	public boolean isCurrentlyInCreation(String beanName) {
		Assert.notNull(beanName, "Bean name must not be null");
		return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName));
	}
	/**
	 * 返回當前Bean實際上是否在建立中
	 *
	 * @param beanName
	 * @return
	 */
	protected boolean isActuallyInCreation(String beanName) {
		return isSingletonCurrentlyInCreation(beanName);
	}
	/**
	 * Return whether the specified singleton bean is currently in creation
	 * (within the entire factory).
	 * 返回指定的單例 bean 當前是否正在建立中
	 *
	 * @param beanName the name of the bean
	 */
	public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}
	/**
	 * Callback before singleton creation.
	 * <p>The default implementation register the singleton as currently in creation.
	 * 單例Bean建立前回撥方法,預設實現將單例註冊為當前正在建立中
	 *
	 * @param beanName the name of the singleton about to be created
	 * @see #isSingletonCurrentlyInCreation
	 */
	protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}
	/**
	 * Callback after singleton creation.
	 * <p>The default implementation marks the singleton as not in creation anymore.
	 * 建立單例後回撥。 預設實現將單例標記為不再建立。
	 *
	 * @param beanName the name of the singleton that has been created
	 * @see #isSingletonCurrentlyInCreation
	 */
	protected void afterSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
		}
	}
	/**
	 * Add the given bean to the list of disposable beans in this registry.
	 * <p>Disposable beans usually correspond to registered singletons,
	 * matching the bean name but potentially being a different instance
	 * (for example, a DisposableBean adapter for a singleton that does not
	 * naturally implement Spring's DisposableBean interface).
	 * 將給定的 bean 新增到此登入檔中的一次性 bean 列表中。 一次性 bean 通常對應於已註冊的單例,
	 * 與 bean 名稱匹配,但可能是不同的範例(例如,單例的 DisposableBean 介面卡不自然實現 Spring 的 DisposableBean 介面)。
	 *
	 * @param beanName the name of the bean
	 * @param bean     the bean instance
	 */
	public void registerDisposableBean(String beanName, DisposableBean bean) {
		synchronized (this.disposableBeans) {
			this.disposableBeans.put(beanName, bean);
		}
	}
	/**
	 * Register a containment relationship between two beans,
	 * e.g. between an inner bean and its containing outer bean.
	 * <p>Also registers the containing bean as dependent on the contained bean
	 * in terms of destruction order.
	 * 註冊兩個 bean 之間的包含關係,例如在內部 bean 和包含它的外部 bean 之間。還根據銷燬順序將包含的 bean 註冊為依賴於所包含的 bean。
	 *
	 * @param containedBeanName  the name of the contained (inner) bean
	 * @param containingBeanName the name of the containing (outer) bean
	 * @see #registerDependentBean
	 */
	public void registerContainedBean(String containedBeanName, String containingBeanName) {
		synchronized (this.containedBeanMap) {
			Set<String> containedBeans =
					this.containedBeanMap.computeIfAbsent(containingBeanName, k -> new LinkedHashSet<>(8));
			if (!containedBeans.add(containedBeanName)) {
				return;
			}
		}
		registerDependentBean(containedBeanName, containingBeanName);
	}
	/**
	 * Register a dependent bean for the given bean,
	 * to be destroyed before the given bean is destroyed.
	 *
	 * @param beanName          the name of the bean
	 * @param dependentBeanName the name of the dependent bean
	 */
	public void registerDependentBean(String beanName, String dependentBeanName) {
		//獲取原始的beanName
		String canonicalName = canonicalName(beanName);
		// 新增 <canonicalName, <dependentBeanName>> 到 dependentBeanMap 中
		synchronized (this.dependentBeanMap) {
			Set<String> dependentBeans =
					this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
			if (!dependentBeans.add(dependentBeanName)) {
				return;
			}
		}
		// 新增 <dependentBeanName, <canonicalName>> 到 dependenciesForBeanMap 中
		synchronized (this.dependenciesForBeanMap) {
			Set<String> dependenciesForBean =
					this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
			dependenciesForBean.add(canonicalName);
		}
	}
	/**
	 * Determine whether the specified dependent bean has been registered as
	 * dependent on the given bean or on any of its transitive dependencies.
	 * 判斷指定的 bean 是否依賴於 dependentBeanName 。
	 *
	 * @param beanName          the name of the bean to check
	 * @param dependentBeanName the name of the dependent bean
	 * @since 4.0
	 */
	//判斷指定的 bean 是否依賴於 dependentBeanName
	protected boolean isDependent(String beanName, String dependentBeanName) {
		synchronized (this.dependentBeanMap) {
			return isDependent(beanName, dependentBeanName, null);
		}
	}
	//判斷指定的 bean 是否依賴於 dependentBeanName
	private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
		// alreadySeen 已經檢測的依賴 bean
		if (alreadySeen != null && alreadySeen.contains(beanName)) {
			return false;
		}
		// 獲取原始 beanName
		String canonicalName = canonicalName(beanName);
		//獲取建立當前bean 所依賴的bean的名稱集合
		Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
		//不依賴任何前置Bean 直接返回
		if (dependentBeans == null) {
			return false;
		}
		// 存在,則證明存在已經註冊的依賴
		if (dependentBeans.contains(dependentBeanName)) {
			return true;
		}
		// 遞迴檢測依賴
		for (String transitiveDependency : dependentBeans) {
			if (alreadySeen == null) {
				alreadySeen = new HashSet<>();
			}
			// 新增到 alreadySeen 中
			alreadySeen.add(beanName);
			//遞迴檢查依賴
			if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
				return true;
			}
		}
		return false;
	}
	/**
	 * Determine whether a dependent bean has been registered for the given name.
	 *
	 * @param beanName the name of the bean to check
	 */
	//判斷beanName是否註冊為依賴Bean
	protected boolean hasDependentBean(String beanName) {
		return this.dependentBeanMap.containsKey(beanName);
	}
	/**
	 * Return the names of all beans which depend on the specified bean, if any.
	 * 返回Bean所依賴的所有Bean集合
	 *
	 * @param beanName the name of the bean
	 * @return the array of dependent bean names, or an empty array if none
	 */
	public String[] getDependentBeans(String beanName) {
		//Bean依賴集合
		Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
		if (dependentBeans == null) {
			return new String[0];
		}
		synchronized (this.dependentBeanMap) {
			return StringUtils.toStringArray(dependentBeans);
		}
	}
	/**
	 * Return the names of all beans that the specified bean depends on, if any.
	 * 返回Bean所依賴的所有Bean集合
	 *
	 * @param beanName the name of the bean
	 * @return the array of names of beans which the bean depends on,
	 * or an empty array if none
	 */
	public String[] getDependenciesForBean(String beanName) {
		Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(beanName);
		if (dependenciesForBean == null) {
			return new String[0];
		}
		synchronized (this.dependenciesForBeanMap) {
			return StringUtils.toStringArray(dependenciesForBean);
		}
	}
	/**
	 * 銷燬所有bean的所有資訊
	 */
	public void destroySingletons() {
		if (logger.isTraceEnabled()) {
			logger.trace("Destroying singletons in " + this);
		}
		//標記為正在銷燬
		synchronized (this.singletonObjects) {
			this.singletonsCurrentlyInDestruction = true;
		}
		String[] disposableBeanNames;
		//獲取需要銷燬的Bean集合
		synchronized (this.disposableBeans) {
			disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
		}
		//迴圈校徽單例Bean
		for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
			destroySingleton(disposableBeanNames[i]);
		}
		//	清空依賴和對映關係快取
		this.containedBeanMap.clear();
		this.dependentBeanMap.clear();
		this.dependenciesForBeanMap.clear();
		// 清理Bean的一級二級三級快取
		clearSingletonCache();
	}
	/**
	 * Clear all cached singleton instances in this registry.
	 * 清除所有快取的單例範例。
	 *
	 * @since 4.3.15
	 */
	protected void clearSingletonCache() {
		synchronized (this.singletonObjects) {
			this.singletonObjects.clear();
			this.singletonFactories.clear();
			this.earlySingletonObjects.clear();
			this.registeredSingletons.clear();
			this.singletonsCurrentlyInDestruction = false;
		}
	}
	/**
	 * Destroy the given bean. Delegates to {@code destroyBean}
	 * if a corresponding disposable bean instance is found.
	 *
	 * @param beanName the name of the bean
	 * @see #destroyBean
	 */
	public void destroySingleton(String beanName) {
		// Remove a registered singleton of the given name, if any.
		//從快取中移除當前bean的相關資訊,由於不知道在哪裡發生異常,所以我們把跟當前bean的所有快取記錄都清除
		removeSingleton(beanName);
		// Destroy the corresponding DisposableBean instance.
		//建立一個變數用於接受 實現了DisposableBean介面的物件變數
		DisposableBean disposableBean;
		synchronized (this.disposableBeans) {
			disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
		}
		//進行bean的銷燬
		destroyBean(beanName, disposableBean);
	}
	/**
	 * Destroy the given bean. Must destroy beans that depend on the given
	 * bean before the bean itself. Should not throw any exceptions.
	 * 銷燬bean的依賴關係
	 *
	 * @param beanName the name of the bean
	 * @param bean     the bean instance to destroy
	 */
	protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
		// Trigger destruction of dependent beans first...
		// 銷燬dependentBeanMap中儲存的是當前bean和依賴bean之間的對映
		Set<String> dependencies;
		synchronized (this.dependentBeanMap) {
			// Within full synchronization in order to guarantee a disconnected Set
			//把當前建立dependon 依賴的bean從快取中移除並且返回處理
			dependencies = this.dependentBeanMap.remove(beanName);
		}
		//如果bean依賴不為空
		if (dependencies != null) {
			if (logger.isTraceEnabled()) {
				logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
			}
			//遞迴銷燬bean
			for (String dependentBeanName : dependencies) {
				destroySingleton(dependentBeanName);
			}
		}
		// Actually destroy the bean now...
		//真正的呼叫bean的destory()方法
		if (bean != null) {
			try {
				bean.destroy();
			} catch (Throwable ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
				}
			}
		}
		// 刪除bean的屬性關係的對映
		Set<String> containedBeans;
		synchronized (this.containedBeanMap) {
			// Within full synchronization in order to guarantee a disconnected Set
			containedBeans = this.containedBeanMap.remove(beanName);
		}
		if (containedBeans != null) {
			for (String containedBeanName : containedBeans) {
				destroySingleton(containedBeanName);
			}
		}
		// Remove destroyed bean from other beans' dependencies.
		//銷燬dependentBeanMap 中 Bean的依賴
		synchronized (this.dependentBeanMap) {
			for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext(); ) {
				Map.Entry<String, Set<String>> entry = it.next();
				Set<String> dependenciesToClean = entry.getValue();
				dependenciesToClean.remove(beanName);
				if (dependenciesToClean.isEmpty()) {
					it.remove();
				}
			}
		}
		// Remove destroyed bean's prepared dependency information.
		//從dependenciesForBeanMap集合移除
		this.dependenciesForBeanMap.remove(beanName);
	}
	/**
	 * Exposes the singleton mutex to subclasses and external collaborators.
	 * <p>Subclasses should synchronize on the given Object if they perform
	 * any sort of extended singleton creation phase. In particular, subclasses
	 * should <i>not</i> have their own mutexes involved in singleton creation,
	 * to avoid the potential for deadlocks in lazy-init situations.
	 */
	/**
	 * 將單例互斥體暴露給子類和外部合作者。 如果子類執行任何型別的擴充套件單例建立階段,
	 * 它們應該在給定的物件上同步。特別是子類不應該在單例建立中使用它們自己的互斥鎖,
	 * 以避免在惰性初始化情況下潛在的死鎖。
	 */
	@Override
	public final Object getSingletonMutex() {
		return this.singletonObjects;
	}
}

它的方法大多為私有的,可以通過debug和反射,在這裡我們通過反射來獲取私有的成員變數:

  // DefaultSingletonBeanRegistry類管理所有的單例物件
     //獲取所有的私有成員變數
        Field singletonObjects = 
       DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
      //允許可以存取私有成員變數
        singletonObjects.setAccessible(true);
        //通過反射獲取
       //獲取beanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
      //反射呼叫,獲取beanFactory的屬性
        Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
       //過濾,獲取component相關的
        map.entrySet().stream().filter(e -> e.getKey().startsWith("component"))
                .forEach(e -> {
                    System.out.println(e.getKey() + "=" + e.getValue());
                });

總結:

BeanFactory 能幹點啥?

  • 表面上只有 getBean
  • 實際上控制反轉、基本的依賴注入、直至 Bean 的生命週期的各種功能,都由它的實現類提供
  • 例子中通過反射檢視了它的成員變數 singletonObjects,內部包含了所有的單例 bean

到此這篇關於Spring BeanFactory工廠使用教學的文章就介紹到這了,更多相關Spring BeanFactory內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com