引言
在上一篇文章中,我們大緻介紹了
Bean
建立、
Bean
加載的流程,但是由于文章篇幅所限,不能事無巨細的進行詳細介紹。後續本系列的文章将對這部分的内容進行庖丁解牛,盡可能的将
IOC
中比較重要的細節說明清楚,以便于自己以及花時間閱讀本文的讀者可以加深對于
Spring IOC
的深入了解。
-
BeanDefinition
-
BeanDefinitionRegistry
- 總結
一、 BeanDefinition
BeanDefinition
納尼,你還要說
Spring IOC
,之前的文章你還沒有說夠嘛?
誰讓
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
隻是一個接口,它的具體實作如下所示:
二、 BeanDefinitionRegistry
BeanDefinitionRegistry
BeanDefinitionRegistry
繼承了
AliasRegistry
接口,其核心子類有三個:
SimpleBeanDefinitionRegistry
、
DefaultListableBeanFactory
以及
GenericApplicationContext
,類機構圖如下所示:
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
的類實作結構如下所示:
這裡關注下實作類
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);
三、 總結
總結