上文對Spring IOC容器的核心BeanFactory接口分析發現:在默認Bean工廠DefaultListableBeanFactory中對象不是以Object形成存儲,而是以BeanDefinition類封裝后存放在並發容器ConcurrentHashMap中的,如下所示:
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
下面來對BeanDefinition接口進行分析。
BeanDefinition
首先來看一幅圖,BeanDefinition接口的UML類圖關系:
可以看到BeanDefinition接口繼承了兩個接口,這兩個接口均為祖宗級接口。AtributeAccessor位於spring-core包下,定義了屬性的操作方式;BeanMetadataElement位於spring-beans包下,定義了獲取元數據元素的配置源。其源碼如下:
package org.springframework.beans.factory.config;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;
void setParentName(String parentName);
String getParentName();
void setBeanClassName(String beanClassName);
String getBeanClassName();
void setScope(String scope);
String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(String... dependsOn);
String[] getDependsOn();
void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(String factoryBeanName);
String getFactoryBeanName();
void setFactoryMethodName(String factoryMethodName);
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
MutablePropertyValues getPropertyValues();
boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
int getRole();
String getDescription();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}
考慮到篇幅限制,將源碼中注釋部分去掉。從接口名字即可大致知道該接口實現了哪些功能。
setParentName(String parentName)
,getParentName()
可以設置獲取該bean的父類beansetBeanClassName(String beanClassName)
,getBeanClassName()
可以設置獲取該bean的別名setLazyInit(boolean lazyInit)
讀取配置文件,設置該bean是否延遲加載;isLazyInit()
判斷該bean是否延遲加載setDependsOn(String... dependsOn)
設置bean的依賴項,String[] getDependsOn()
獲取依賴項setFactoryBeanName(String factoryBeanName)
設置該bean的加載工廠,String getFactoryBeanName()
獲取bean的加載工廠
通過對接口方法分析,可以發現BeanDefinition定義了bean實例的基礎方法,基本上通過BeanDefinition接口就可以描述一個bean對象。也即表面在beanDefinitionMap
中BeanDefinition接口可以替代Object對象存儲bean實例。
既然兩者都可以存儲bean對象,為啥是用BeanDefinition而不是Object呢?其實細究可以發現:在Spring中,我們可以自定義是否延遲加載bean對象,合適初始化對象,要想實現加載、初始化時機控制,簡單的通過Object對象是無法實現的,必須在此基礎上有一個封裝,這樣才可以實現更多的自定義性質。所以在beanDefinitionMap
中bean對象是以BeanDefinition形式存儲。
本文介紹了Spring IOC容器中一個非常重要的接口BeanDefinition,以及解釋了為啥beanDefinitionMap
中存儲的是BeanDefinition。下文將進入Spring IOC類加載的具體過程,重點看看默認的bean工廠DefaultListableBeanFactory