這篇文章分析的代碼:
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//如果不是僅僅做類型檢查則是創建bean,這裏需要記錄 將beanName緩存在alreadyCreatedz中
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 從容器中獲取 beanName 相應的 GenericBeanDefinition,並將其轉換爲 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 檢查給定的合併的 BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
//獲取depends-on的屬性值,如果depends-on的值存在 則添加進入dependentBeanMap緩存中
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
這段代碼處理的邏輯是:
- 如果bean是原型模式並處於創建中,則拋出異常。
- 如果beanDefinitionMap中不存在對應beanName的BeanDefinition,那麼嘗試從parentBeanFactory中加載。
- 判斷是否檢查類型
- 從 mergedBeanDefinitions 中獲取 beanName 對應的 RootBeanDefinition
- 檢查dependes-on依賴
1. isPrototypeCurrentlyInCreation方法
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
Spring對於處於原型模式的正在創建的bean的依賴會拋出異常。
2.pareentBeanFactory加載
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//獲取原始name
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
//加入parentBeanFactory是AbstractBeanFactory類型
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
//args不爲空情況下,委託方法
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
////標準情況下,委託方法
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
如果beanDefinitionMap沒有包含beanName對應的BeanDefinition,則從parentBeanFactory中加載。
originalBeanName()方法作用:如果name是以&開頭的,那麼beanName也要加上這個標誌。
3.類型檢查
參數typeCheckOnly判斷bean是否爲類型檢查獲取bean。如果不是則需要調用markBeanAsCreated()緩存起來.
protected void markBeanAsCreated(String beanName) {
//判斷已創建是否包含beanName
if (!this.alreadyCreated.contains(beanName)) {
// 獲取全局鎖
synchronized (this.mergedBeanDefinitions) {
//雙重判斷
if (!this.alreadyCreated.contains(beanName)) {
// 從 mergedBeanDefinitions 中刪除 beanName,
// 並在下次訪問時重新創建它。
clearMergedBeanDefinition(beanName);
// 添加到已創建bean 集合中
this.alreadyCreated.add(beanName);
}
}
}
}
4. 獲取RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
getMergedLocalBeanDefinition():作用主要是將獲取beanName對應的RootBeanDefinition對象
checkMergedBeanDefinition()則是檢查創建的RootBeanDefinition對象。
5.處理depends-on
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
//獲取depends-on的屬性值,如果depends-on的值存在 則添加進入dependentBeanMap緩存中
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 單例模式下創建bean
處理bean的依賴思路大致是:
- 獲取depends-on依賴,如果depends-on不爲空,檢查beanName和依賴是否已經存在依賴關係。
- 如果存在拋出異常,不存在則緩存對應的依賴。
isDependent方法:檢測beaName和dependsOn是否存在已存在依賴。
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
//獲取原始的beanName
String canonicalName = canonicalName(beanName);
//獲取beaName的依賴集合
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
//包含,則證明已經處於註冊依賴
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
//遞歸檢測
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
registerDependentBean方法註冊bean的依賴關係
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}
將依賴映射關係保存:dependentBeanMap、dependenciesForBeanMap。
最後調用getBean()實例化bean。