Spring原始碼之IOC(一)BeanDefinition原始碼解析

ONROAD0612發表於2018-12-04

1 概述

Bean的定義主要是由BeanDefinition來描述的。BeanDefinition是Spring中包裝bean的資料結構,她描述了一個bean例項屬性、構造引數。當然針對她的具體實現類提供了更加豐富的功能。這僅僅是一個基本的介面,這個介面的主要目的是允許修改和獲取bean的屬性和後設資料。

2 類關係

針對BeanDefinition,我們首先來看一下UML類圖。

從上圖我們可以看出BeanDefinition是一個介面,並且繼承了AttributeAccessor和BeanMetadataElement這兩個介面。我們來看一下這兩個介面做了什麼。

(1)AttributeAccessor

這個介面主要定義了一些對任意物件的後設資料的訪問的函式,具體的原始碼如下。

public interface AttributeAccessor {

	//設定指定名稱的屬性為指定的內容,當然如果這個內容為null就相當於將這個屬性進行了刪除。
	void setAttribute(String name, @Nullable Object value);

	//獲取指定名稱的屬性值
	@Nullable
	Object getAttribute(String name);

	//移除指定名稱的屬性
	@Nullable
	Object removeAttribute(String name);

	//判斷物件是否有對應名稱的屬性
	boolean hasAttribute(String name);

	//獲取所有屬性名稱的陣列
	String[] attributeNames();
}

(2)BeanMetadataElement

返回後設資料元素的配置源物件,這個類就僅僅包含了一個getResource函式。

3 屬性

(1) SCOPE_SINGLETON

這是一個bean為單列時候的一個識別符號。

(2) SCOPE_PROTOTYPE

這是一個bean為非單列時候的標識服。這裡針對單列和非單列簡單說明一下。
單列是在整個程式執行的過程當中僅僅只有一個對應的物件被建立,比如我們常見的配置類,這在整個程式執行的過程中就只有一個。
非單列,是在每次使用類對應的bean的時候都重新建立對應的物件,當然如果類包含狀態的時候我們就考慮使用非單列。

(3) ROLE_APPLICATION

表示這個bean是應用程式的主要部分。

(4) ROLE_SUPPORT

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

(5) ROLE_INFRASTRUCTURE

表明一個BeanDefinition是提供一個完全背景的角色,並且與終端使用者沒有關係。這個提示用於註冊完全是ComponentDefinition內部工作的一部分的bean。

4 函式

真針對函式部分的學習,我們直接檢視原始碼部分吧,這些函式其實主要是對一些基礎屬性的訪問器和修改器。

        /**
	 * Set the name of the parent definition of this bean definition, if any.
	 */
	void setParentName(@Nullable String parentName);

	/**
	 * Return the name of the parent definition of this bean definition, if any.
	 */
	@Nullable
	String getParentName();

	/**
	 * Specify the bean class name of this bean definition.
	 * <p>The class name can be modified during bean factory post-processing,
	 * typically replacing the original class name with a parsed variant of it.
	 * @see #setParentName
	 * @see #setFactoryBeanName
	 * @see #setFactoryMethodName
	 */
	void setBeanClassName(@Nullable String beanClassName);

	/**
	 * Return the current bean class name of this bean definition.
	 * <p>Note that this does not have to be the actual class name used at runtime, in
	 * case of a child definition overriding/inheriting the class name from its parent.
	 * Also, this may just be the class that a factory method is called on, or it may
	 * even be empty in case of a factory bean reference that a method is called on.
	 * Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
	 * rather only use it for parsing purposes at the individual bean definition level.
	 * @see #getParentName()
	 * @see #getFactoryBeanName()
	 * @see #getFactoryMethodName()
	 */
	@Nullable
	String getBeanClassName();

	/**
	 * Override the target scope of this bean, specifying a new scope name.
	 * @see #SCOPE_SINGLETON
	 * @see #SCOPE_PROTOTYPE
	 */
	void setScope(@Nullable String scope);

	/**
	 * Return the name of the current target scope for this bean,
	 * or {@code null} if not known yet.
	 */
	@Nullable
	String getScope();

	/**
	 * Set whether this bean should be lazily initialized.
	 * <p>If {@code false}, the bean will get instantiated on startup by bean
	 * factories that perform eager initialization of singletons.
	 */
	void setLazyInit(boolean lazyInit);

	/**
	 * Return whether this bean should be lazily initialized, i.e. not
	 * eagerly instantiated on startup. Only applicable to a singleton bean.
	 */
	boolean isLazyInit();

	/**
	 * Set the names of the beans that this bean depends on being initialized.
	 * The bean factory will guarantee that these beans get initialized first.
	 */
	void setDependsOn(@Nullable String... dependsOn);

	/**
	 * Return the bean names that this bean depends on.
	 */
	@Nullable
	String[] getDependsOn();

	/**
	 * Set whether this bean is a candidate for getting autowired into some other bean.
	 * <p>Note that this flag is designed to only affect type-based autowiring.
	 * It does not affect explicit references by name, which will get resolved even
	 * if the specified bean is not marked as an autowire candidate. As a consequence,
	 * autowiring by name will nevertheless inject a bean if the name matches.
	 */
	void setAutowireCandidate(boolean autowireCandidate);

	/**
	 * Return whether this bean is a candidate for getting autowired into some other bean.
	 */
	boolean isAutowireCandidate();

	/**
	 * Set whether this bean is a primary autowire candidate.
	 * <p>If this value is {@code true} for exactly one bean among multiple
	 * matching candidates, it will serve as a tie-breaker.
	 */
	void setPrimary(boolean primary);

	/**
	 * Return whether this bean is a primary autowire candidate.
	 */
	boolean isPrimary();

	/**
	 * Specify the factory bean to use, if any.
	 * This the name of the bean to call the specified factory method on.
	 * @see #setFactoryMethodName
	 */
	void setFactoryBeanName(@Nullable String factoryBeanName);

	/**
	 * Return the factory bean name, if any.
	 */
	@Nullable
	String getFactoryBeanName();

	/**
	 * Specify a factory method, if any. This method will be invoked with
	 * constructor arguments, or with no arguments if none are specified.
	 * The method will be invoked on the specified factory bean, if any,
	 * or otherwise as a static method on the local bean class.
	 * @see #setFactoryBeanName
	 * @see #setBeanClassName
	 */
	void setFactoryMethodName(@Nullable String factoryMethodName);

	/**
	 * Return a factory method, if any.
	 */
	@Nullable
	String getFactoryMethodName();

	/**
	 * Return the constructor argument values for this bean.
	 * <p>The returned instance can be modified during bean factory post-processing.
	 * @return the ConstructorArgumentValues object (never {@code null})
	 */
	ConstructorArgumentValues getConstructorArgumentValues();

	/**
	 * Return if there are constructor argument values defined for this bean.
	 * @since 5.0.2
	 */
	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	/**
	 * Return the property values to be applied to a new instance of the bean.
	 * <p>The returned instance can be modified during bean factory post-processing.
	 * @return the MutablePropertyValues object (never {@code null})
	 */
	MutablePropertyValues getPropertyValues();

	/**
	 * Return if there are property values values defined for this bean.
	 * @since 5.0.2
	 */
	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}


	// Read-only attributes

	/**
	 * Return whether this a <b>Singleton</b>, with a single, shared instance
	 * returned on all calls.
	 * @see #SCOPE_SINGLETON
	 */
	boolean isSingleton();

	/**
	 * Return whether this a <b>Prototype</b>, with an independent instance
	 * returned for each call.
	 * @since 3.0
	 * @see #SCOPE_PROTOTYPE
	 */
	boolean isPrototype();

	/**
	 * Return whether this bean is "abstract", that is, not meant to be instantiated.
	 */
	boolean isAbstract();

	/**
	 * Get the role hint for this {@code BeanDefinition}. The role hint
	 * provides the frameworks as well as tools with an indication of
	 * the role and importance of a particular {@code BeanDefinition}.
	 * @see #ROLE_APPLICATION
	 * @see #ROLE_SUPPORT
	 * @see #ROLE_INFRASTRUCTURE
	 */
	int getRole();

	/**
	 * Return a human-readable description of this bean definition.
	 */
	@Nullable
	String getDescription();

	/**
	 * Return a description of the resource that this bean definition
	 * came from (for the purpose of showing context in case of errors).
	 */
	@Nullable
	String getResourceDescription();

	/**
	 * Return the originating BeanDefinition, or {@code null} if none.
	 * Allows for retrieving the decorated bean definition, if any.
	 * <p>Note that this method returns the immediate originator. Iterate through the
	 * originator chain to find the original BeanDefinition as defined by the user.
	 */
	@Nullable
	BeanDefinition getOriginatingBeanDefinition();

利用註釋我們可以理解每個函式的具體作用,我們這裡就不進行一一解釋了。

通過上面的分析,我們對BeanDefinition有了個深入的認識,接下來我們會對BeanDefinition的子類進行詳細分析,歡迎交流。

 

相關文章