天天看點

Spring原理學習系列之六:IOC原理之BeanDefinition注冊

引言

在上一篇文章中,我們大緻介紹了

Bean

建立、

Bean

加載的流程,但是由于文章篇幅所限,不能事無巨細的進行詳細介紹。後續本系列的文章将對這部分的内容進行庖丁解牛,盡可能的将

IOC

中比較重要的細節說明清楚,以便于自己以及花時間閱讀本文的讀者可以加深對于

Spring IOC

的深入了解。

  • BeanDefinition

  • BeanDefinitionRegistry

  • 總結

一、

BeanDefinition

納尼,你還要說

Spring IOC

,之前的文章你還沒有說夠嘛?

Spring原理學習系列之六:IOC原理之BeanDefinition注冊

誰讓

Spring

中關于

IOC

這部分的内容這麼多呢,前面的文章還沒有說的很細。是以隻能繼續慢慢往下唠叨了。廢話不多說,我們來繼續

IOC

BeanDefinition

是用來描述

Spring

中的

Bean

,是包裝Bean的資料結構。其源碼如下所示:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	
	//标準單例作用域的作用域辨別符:“singleton”,對于擴充的bean工廠可能支援更多的作用域
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

	//标準原型作用域的範圍辨別符:“prototype”
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;


	//表示BeanDefinition是應用程式主要部分的角色提示,通常對應于使用者定義的bean
	int ROLE_APPLICATION = 0;

	//表示BeanDefinition是某些大型配置的支援部分的角色提示,通常是一個外部ComponentDefinition。
	//當檢視某個特定的ComponentDefinition時,認為bean非常重要,
	//以便在檢視應用程式的整體配置時能夠意識到這一點
	int ROLE_SUPPORT = 1;

	//角色提示表明一個BeanDefinition是提供一個完全背景的角色,并且與最終使用者沒有關系。
	//這個提示用于注冊完全是ComponentDefinition内部工作的一部分的bean
	int ROLE_INFRASTRUCTURE = 2;

	//1、目前Bean父類名稱
	//如果父類存在,設定這個bean定義的父定義的名稱
	void setParentName(@Nullable String parentName);

	//如果父類存在,則傳回目前Bean的父類的名稱
	@Nullable
	String getParentName();

	//2、目前Bean的className
	//指定此bean定義的bean類名稱。
	//類名稱可以在bean factory後期進行中修改,通常用它的解析變體替換原來的類名稱
	void setBeanClassName(@Nullable String beanClassName);

	//傳回此bean定義的目前bean類名稱
	//需要注意的是,這不一定是在運作時使用的實際類名,以防子類定義覆寫/繼承其父類的類名
	//此外,這可能隻是調用工廠方法的類,或者它 在調用方法的工廠bean引用的情況下甚至可能是空的
	//是以,不要認為這是在運作時定義的bean類型,而隻是将其用于在單獨的bean定義級别進行解析
	@Nullable
	String getBeanClassName();

	//3、bean作用域
	//覆寫此bean的目标範圍,指定一個新的範圍名稱
	void setScope(@Nullable String scope);

	//傳回此bean的目前目标作用域的名稱,如果沒有确定,傳回null
	@Nullable
	String getScope();

	//懶加載
	//設定這個bean是否應該被延遲初始化。如果{false},那麼這個bean将在啟動時由bean工廠執行個體化,
	//這些工廠執行單例的立即初始化。
	//懶加載 <bean lazy-init="true/false">
	void setLazyInit(boolean lazyInit);

	//傳回這個bean是否應該被延遲初始化,即不是在啟動時立即執行個體化。隻适用于單例bean。
	boolean isLazyInit();

	//5.依賴關系設定
	//設定這個bean依賴被初始化的bean的名字。 bean工廠将保證這些bean首先被初始化。
	//<bean depends-on="">
	void setDependsOn(@Nullable String... dependsOn);

	//傳回這個bean依賴的bean名稱
	@Nullable
	String[] getDependsOn();

	//6.是否是自動轉配設定
	//設定這個bean是否是獲得自動裝配到其他bean的候選人。
	//需要注意是,此标志旨在僅影響基于類型的自動裝配。
	//它不會影響按名稱的顯式引用,即使指定的bean沒有标記為autowire候選,也可以解決這個問題。
	//是以,如果名稱比對,通過名稱的自動裝配将注入一個bean。
	void setAutowireCandidate(boolean autowireCandidate);

	//傳回這個bean是否是自動裝配到其他bean的候選者。就是是否在其他類中使用autowired來注入目前Bean的
	//是否為被自動裝配 <bean autowire-candidate="true/false">
	boolean isAutowireCandidate();

	//7.主候選Bean
	//是否為主候選bean    使用注解:@Primary
	
	void setPrimary(boolean primary);
	
	//傳回這個bean是否是主要的autowire候選者
	boolean isPrimary();

	//8.定義建立該Bean對象的工廠類
	//指定要使用的工廠bean(如果有的話), 這是調用指定的工廠方法的bean的名稱
	void setFactoryBeanName(@Nullable String factoryBeanName);

	//如果有傳回工廠bean的名字
	@Nullable
	String getFactoryBeanName();

	//9.建立該Bean對象的工廠方法
	//如果有,指定工廠方法。這個方法先将通過構造函數參數被調用,或者如果參數,将調用該方法的無參數構造
	void setFactoryMethodName(@Nullable String factoryMethodName);
	//如果存在,傳回工廠方法名
	@Nullable
	String getFactoryMethodName();

	//10.傳回此bean的構造函數參數值
	//傳回此bean的構造函數參數值
	ConstructorArgumentValues getConstructorArgumentValues();

	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	//11.擷取屬性
	MutablePropertyValues getPropertyValues();

	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	//12.設定初始方法
	void setInitMethodName(@Nullable String initMethodName);

	@Nullable
	String getInitMethodName();


	void setDestroyMethodName(@Nullable String destroyMethodName);

	@Nullable
	String getDestroyMethodName();


	void setRole(int role);

	//13.目前Bean的角色
	//擷取這個bean的角色
	int getRole();

	void setDescription(@Nullable String description);

	//14.可讀描述
	//傳回對bean定義的可讀描述
	@Nullable
	String getDescription();

	//傳回該bean定義來自的資源的描述
	@Nullable
	String getResourceDescription();

	//傳回原始的BeanDefinition;如果沒有,則傳回null。允許檢索裝飾的bean定義
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();
	
	//15.目前Bean的基本特性
	//是否是單例的
	boolean isSingleton();

	//是否是多例的
	boolean isPrototype();

	//是否是抽象類
	boolean isAbstract();

	

}
           

從上面的屬性和方法分析可以看出,

BeanDefinition

對于一個

Bean

的描述做了比較完整的一套限制。這為後續的實作類提供了最基本的職責和屬性。

BeanDefinition

隻是一個接口,它的具體實作如下所示:

Spring原理學習系列之六:IOC原理之BeanDefinition注冊

二、

BeanDefinitionRegistry

BeanDefinitionRegistry

繼承了

AliasRegistry

接口,其核心子類有三個:

SimpleBeanDefinitionRegistry

DefaultListableBeanFactory

以及

GenericApplicationContext

,類機構圖如下所示:

Spring原理學習系列之六:IOC原理之BeanDefinition注冊

AliasRegistry

作為

BeanDefinitionRegistry

的頂層接口,它的作用主要為别名管理的通用型接口,

AliasRegistry

定義了一些别名管理的方法。

public interface AliasRegistry {

	
	void registerAlias(String name, String alias);

	
	void removeAlias(String alias);

	
	boolean isAlias(String name);


	String[] getAliases(String name);

}
           

BeanDefinitionRegistry

接口在實作

AliasRegistry

之外還定義了關于

BeanDefinition

注冊、登出、查詢等一系列的操作。

public interface BeanDefinitionRegistry extends AliasRegistry {

	// 向系統資料庫中注冊一個新的 BeanDefinition 執行個體
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

	 // 移除系統資料庫中已注冊的 BeanDefinition 執行個體
	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	 // 從注冊中取得指定的 BeanDefinition 執行個體
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	 // 判斷 BeanDefinition 執行個體是否在系統資料庫中(是否注冊)
	boolean containsBeanDefinition(String beanName);

	// 取得系統資料庫中所有 BeanDefinition 執行個體的 beanName(辨別)
	String[] getBeanDefinitionNames();

	// 傳回系統資料庫中 BeanDefinition 執行個體的數量
	int getBeanDefinitionCount();

	// beanName(辨別)是否被占用
	boolean isBeanNameInUse(String beanName);

}

           

我們可以看下

BeanDefinitionRegistry

的類實作結構如下所示:

Spring原理學習系列之六:IOC原理之BeanDefinition注冊

這裡關注下實作類

GenericApplicationContext

,其中比較重要的方法為

registerBeanDefinition

,它完成了

BeanDefinition

的注冊 :

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

	private final DefaultListableBeanFactory beanFactory;
	
	...
	
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
	}
	...
}
           
@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}
           
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

this.beanDefinitionMap.put(beanName, beanDefinition);
           

三、

總結