Spring原始碼分析之Bean的建立過程詳解

雕爺的架構之路發表於2020-10-29

前文傳送門:

  1. Spring原始碼分析之預啟動流程
  2. Spring原始碼分析之BeanFactory體系結構
  3. Spring原始碼分析之BeanFactoryPostProcessor呼叫過程詳解

本文內容:

  1. 在IOC中,是如何通過beanDefition建立出一個bean的?
  2. 各BeanPostProcessor在這過程中扮演的角色,呼叫時機?

話不多說,直接正題走起,上圖!

下面是bean建立過程的大致流程圖,本文將以圖中順序進行逐步原始碼分析,小夥伴亦可與圖中流程邊對照邊品食

原向量圖地址:https://www.processon.com/view/link/5f6174431e08531edf3134fb

img

我們知道,在Spring IOC前段部分有註冊了一系列的BeanPostProcessor,在Bean的建立過程中,就將要使用到他們了,下面我給大家一一列出

  • AutowiredAnnotationBeanPostProcessor:在new AnnotatedBeanDefinitionReader時註冊

  • CommonAnnotationBeanPostProcessor: 在new AnnotatedBeanDefinitionReader時註冊

  • ApplicationContextAwareProcessor: 在prepareBeanFactory時註冊

  • ApplicationListenerDetector: 在prepareBeanFactory時註冊

  • ImportAwareBeanPostProcessor: 在配置類後置處理器呼叫postProcessBeanFactory註冊

  • BeanPostProcessorChecker:在registerBeanPostProcessors時註冊

以上就是Spring中內建的所有BeanPostProcessor了

同樣,我們先從最開始的入口refresh開始分析

public void refresh(){
  //....省略前面部分
  // 例項化剩餘的單例bean
  finishBeanFactoryInitialization(beanFactory);
}

finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory){
  // 將所有非懶載入的bean載入到容器中
	beanFactory.preInstantiateSingletons();
}

迴圈我們之前註冊的所有beanDefinition,一個個的進行呼叫getBean註冊到容器中

public void preInstantiateSingletons(){
  // 迴圈所有beanDefinition
  for (String beanName : beanNames) {
    // 將beanDefinition轉化為RootBeanDefinition
    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    // 不是抽象類並且是單例並且非懶載入
    if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
      // 是否為工廠bean
      if (isFactoryBean(beanName)) {
        // 由於是以&開頭獲取bean,這裡返回的是一個工廠bean,並且不會呼叫getObject方法
        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
        if (bean instanceof FactoryBean) {
          // 判斷是否要立即初始化bean
          FactoryBean<?> factory = (FactoryBean<?>) bean;
          boolean isEagerInit = (factory instanceof SmartFactoryBean &&
                           ((SmartFactoryBean<?>) factory).isEagerInit());
          if (isEagerInit) {
            // 以為&開頭的方式再獲取一次,此時會呼叫FactoryBean的getObject()方法
            getBean(beanName);
          }
        }
      }
      else {
        // 不是FactoryBean,直接使用getBean進行初始化
        getBean(beanName);
      }
    }
  }
}

接下來就是Spring的常規操作,呼叫do開頭的doGetBean

public Object getBean(String name) throws BeansException {
  return doGetBean(name, null, null, false);
}

以下為doGetBean中獲取單例bean的邏輯

// 轉化beanName 如果是以&開頭則去除,如果有別名則獲取別名
String beanName = transformedBeanName(name);
// 嘗試從三級快取中獲取bean
Object sharedInstance = getSingleton(beanName);
// 是否從快取中獲取到了bean
if (sharedInstance != null && args == null) {
  // 如果是工廠類且name不以&開頭,則呼叫工廠類的getObject()
  // 其他情況返回原物件
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

getSingleton

public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 從單例快取池中獲取
		Object singletonObject = this.singletonObjects.get(beanName);
		// 獲取不到,判斷bean是否正在建立
    // 如果是正在建立,2種情況 1.多個執行緒在建立bean 2.發生迴圈依賴
    // 如果是多個執行緒,則由於同步鎖阻塞於此
    // 迴圈依賴的問題較為複雜,將在下章詳細分析
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				// 從早期物件快取池中獲取
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					// 從三級快取中獲取單例工廠
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						// 呼叫回撥方法獲取早期bean
						singletonObject = singletonFactory.getObject();
						// 將早期物件放到二級快取,移除三級快取
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

getObjectForBeanInstance

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		// 判斷name是否以&開頭,是則直接返回該FactoryBean
    /*public static boolean isFactoryDereference(@Nullable String name) {
				return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
		}*/
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}
		// 不是工廠bean直接返回原物件
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}
		// 嘗試從快取中獲取,保證多次從工廠bean獲取的bean是同一個bean
		object = getCachedObjectForFactoryBean(beanName);
		if (object == null) {
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			boolean synthetic = (mbd != null && mbd.isSynthetic());
      // 從FactoryBean獲取物件
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

getObjectFromFactoryBean的程式碼摘取片段

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess){
  // 獲取bean,呼叫factoryBean的getObject()
	object = doGetObjectFromFactoryBean(factory, beanName);
}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName){
  object = factory.getObject();
}

以上為從快取中獲取到bean,處理FactoryBean的邏輯,接下來我們看看實際建立bean的過程

以下為續接上面doGetBean中未從快取中獲取到bean的邏輯

// 如果有被@DependsOn標記,先建立DependsOn的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
  for (String dep : dependsOn) {
    registerDependentBean(dep, beanName);
    getBean(dep);
  }
}
// 單例bean
if (mbd.isSingleton()) {
  // 開始建立bean
  sharedInstance = getSingleton(beanName, () -> {
    // 真正建立bean
    return createBean(beanName, mbd, args);
  });
  // 如果是工廠類且name不以&開頭,則呼叫工廠類的getObject()
  // 其他情況返回原物件
  bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

getSingleton,此方法為過載方法,與從快取中獲取bean並非同一個

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		// 開始建立bean時加鎖,注意這個鎖的同步物件與從快取中獲取時鎖的同步物件相同
		synchronized (this.singletonObjects) {
			// 再次從快取中獲取,有直接返回,出現有的情況
			// 1.執行緒一正在建立A例項,執行緒二嘗試獲取,被同步鎖阻塞
			// 2.執行緒一建立完畢,執行緒二進入同步程式碼塊,從快取中獲取直接返回
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				// 標記正在建立中
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				try {
					// 呼叫回撥函式獲取到bean
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				finally {
					// 清理狀態
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					// 將建立的bean新增到單例快取池中,並移除二三級快取
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

createBean,終於開始建立bean了~

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
  // 第一次呼叫bean後置處理器,在bean例項化之前的進行處理
  // Spring內建的後置處理器中,無相關實現
  // 可使用自定義的後置處理器在這裡進行中止bean的建立過程操作
  Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  if (bean != null) {
    // 如果自定義的後置處理器返回了bean,則直接return,bean的建立過程於此中斷
    return bean;
  }
  // 進行建立bean
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
  // 例項化bean 第二次呼叫bean後置處理器,用於獲取bean的有參構造器
	instanceWrapper = createBeanInstance(beanName, mbd, args);
  // 第三次 處理beanDefinition的後設資料資訊
  applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  // 是否允許暴露早期物件
  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                    isSingletonCurrentlyInCreation(beanName));
  // 第四次 用於獲取早期物件時的處理
  // 將獲取早期物件的回撥方法放到三級快取中
  addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  // 第五、六次,填充屬性 可使用的方式 byName byType @Resource @Value @Autowired @Inject
	populateBean(beanName, mbd, instanceWrapper);
  // 第七、八次,初始化
	exposedObject = initializeBean(beanName, exposedObject, mbd);
  // 第九次 判斷bean是否有銷燬方法,有則將bean註冊到銷燬集合中,用於容器關閉時使用
	registerDisposableBeanIfNecessary(beanName, bean, mbd);
  // 返回建立好的bean
  return exposedObject;
}

你以為這就結束了?

接下來我們就來看看這裡後置處理器到底做了什麼吧

由於第一次呼叫並未有任何處理,我們從第二次呼叫開始分析

createBeanInstance

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
  // 獲取beanClass
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
  // 使用AutowiredAnnotationBeanPostProcessor進行構造器推斷,找到所有的有參構造器
  Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    // 例項化bean,並根據引數自動裝配
    return autowireConstructor(beanName, mbd, ctors, args);
  }
  // 呼叫無參的構造方法例項化
	return instantiateBean(beanName, mbd);
}

determineConstructorsFromBeanPostProcessors

protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
			throws BeansException {
	
  if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
        // 只有AutowiredAnnotationBeanPostProcessor進行了實現,其他的都返回null
        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
        // 確認候選的構造器
        Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
        if (ctors != null) {
          return ctors;
        }
      }
    }
  }
  return null;
}

AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors

public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName){
  // 獲取到所有的構造方法
  rawCandidates = beanClass.getDeclaredConstructors();
  for (Constructor<?> candidate : rawCandidates) {
    // 是否帶有@Autowired註解
    MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
    if (ann != null) {
      // 是否必須
      boolean required = determineRequiredStatus(ann);
      candidates.add(candidate);
    }
    else if (candidate.getParameterCount() == 0) {
      // 無參構造器
      defaultConstructor = candidate;
    }
  }
  // 候選的構造器不為空
  if (!candidates.isEmpty()) {
    // 候選的構造器不為空而requiredConstructor為空表示有@Autowired標識的構造器
    // 但是required=false
    if (requiredConstructor == null) {
      if (defaultConstructor != null) {
        // 將無參構造器也加入到候選構造器集合中
        candidates.add(defaultConstructor);
      }
    }
    // 將集合中的構造器轉化為陣列
    candidateConstructors = candidates.toArray(new Constructor<?>[0]);
  }
  // 候選的構造器為空,但有一個有參構造器,則使用有參構造器作為候選的構造器
  else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
    candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
  }
  // 返回候選構造器陣列
  return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

autowireConstructor 例項化並自動裝配,摘取程式碼片段

protected BeanWrapper autowireConstructor(
			String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {

  return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
  for (Constructor<?> candidate : candidates) {
    // 獲取引數的型別
		Class<?>[] paramTypes = candidate.getParameterTypes();
    // 獲取依賴的bean
    argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames..);
    // 呼叫instantiate方法進行例項化bean
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
  }
}

以上便是bean的例項化過程

applyMergedBeanDefinitionPostProcessors

第三次主要是將標識了需要自動裝配註解的屬性或方法解析出來,包含的註解主要有 @Resource @Autowired @Value @Inject @PostConstruct @PreDestroy

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof MergedBeanDefinitionPostProcessor) {
      // CommonAnnotationBeanPostProcessor解析@PostConstruct @PreDestroy @Resource
      // AutowiredAnnotationBeanPostProcessor 解析@Autowired @Value @Inject
      MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
      bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    }
  }
}

CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
  // 父類為InitDestroyAnnotationBeanPostProcessor
  // 尋找@PostConstruct @PreDestroy註解的方法
  // 用於bean的生命週期中初始化前的處理邏輯
  super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
  // 尋找@Resource註解標識的屬性或方法後設資料
  // 將這些後設資料儲存到快取中,用於在屬性裝配階段使用
  InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
  // 檢查是否有重複的後設資料,去重處理,如一個屬性上既有@Autowired註解,又有@Resource註解
  // 只使用一種方式進行注入,由於@Resource先進行解析,所以會選擇@Resource的方式
  metadata.checkConfigMembers(beanDefinition);
}

InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
  // 尋找PostConstruct @PreDestroy註解的方法
  LifecycleMetadata metadata = findLifecycleMetadata(beanType);
	// 去重處理
  metadata.checkConfigMembers(beanDefinition);
}

所有的後置處理器的過程是相似的,這裡取CommonAnnotationBeanPostProcessor進行分析

我們先來看看尋找後設資料的過程

private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
  String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
  // 從快取中獲取
  // 呼叫postProcessMergedBeanDefinition方法時將後設資料解析放入快取
  // 呼叫postProcessProperties方法時將後設資料取出
  InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
  if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    synchronized (this.injectionMetadataCache) {
      metadata = this.injectionMetadataCache.get(cacheKey);
      if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        if (metadata != null) {
          metadata.clear(pvs);
        }
        // 建立後設資料,尋找@Resouce標識的屬性或方法
        metadata = buildResourceMetadata(clazz);
        this.injectionMetadataCache.put(cacheKey, metadata);
      }
    }
  }
  return metadata;
}

buildResourceMetadata

private InjectionMetadata buildResourceMetadata(final Class<?> clazz){
  // 判斷是否為候選的class,不是則返回預設的空後設資料
  // resourceAnnotationTypes為Annotation集合,裡面包含了@Resource @EJB @WebServiceRef
  // 我們一般常用的只是@Resource
  if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
    return InjectionMetadata.EMPTY;
  }
  do {
    // 迴圈所有的屬性,判斷屬性是否存在WebServiceRef、EJB、Resource註解,有則構建後設資料
    // doWithLocalFields中就是將targetClass的所有field取出進行迴圈
    ReflectionUtils.doWithLocalFields(targetClass, field -> {
      if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
        currElements.add(new WebServiceRefElement(field, field, null));
      }
      else if (ejbClass != null && field.isAnnotationPresent(ejbClass)) {
        currElements.add(new EjbRefElement(field, field, null));
      }
      // 是否存在@Resource註解
      else if (field.isAnnotationPresent(Resource.class)) {
        if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
          currElements.add(new ResourceElement(field, field, null));
        }
      }
    }); 
    // 與上一步相似,判斷方法上是否存在這些註解
    ReflectionUtils.doWithLocalMethods(targetClass, method -> {
      //......省略
    });
    // 獲取父類
    targetClass = targetClass.getSuperclass();
  }
  // 父類不是Object則繼續迴圈父類中的屬性和方法
  while (targetClass != null && targetClass != Object.class);
  // 將構建好的後設資料封裝到InjectionMetadata中返回
  return InjectionMetadata.forElements(elements, clazz);
}

現在我們再來看看去重處理的過程

public void checkConfigMembers(RootBeanDefinition beanDefinition) {
		Set<InjectedElement> checkedElements = new LinkedHashSet<>(this.injectedElements.size());
  for (InjectedElement element : this.injectedElements) {
    Member member = element.getMember();
    // 檢查該beanDefinition的externallyManagedConfigMembers集合中是否已經包含該成員(屬性或者方法)
    if (!beanDefinition.isExternallyManagedConfigMember(member)) {
      // 不包含則將該成員註冊
      beanDefinition.registerExternallyManagedConfigMember(member);
      // 加入到已檢查的集合
      checkedElements.add(element);
    }
  }
  this.checkedElements = checkedElements;
}

由於第四次,用於獲取早期物件時的處理的呼叫,在Spring的內建處理器中也沒有相應的實現,跳過

這一步和第一步一樣,在AOP時將會用到,我們放到下章分析

緊接著就是填充屬性的步驟了

populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
  // 在這裡可進行中止填充屬性操作,實現InstantiationAwareBeanPostProcessor介面
	// 並postProcessAfterInstantiation返回false,則直接返回,不會再往下執行
  // Spring內中的後置處理器皆返回的true
  if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
      if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
          return;
        }
      }
    }
  }
  // 獲得自動裝配的型別,預設為0,
  // 這裡只有xml配置,ImportBeanDefinitionRegistrar,BeanFactoryPostProcessor可進行改變
  // Spring整合Mybatis中,將Mapper的自動裝配型別改成了BY_TYPE,
  // 於是在Mapper得以在這裡被填充SqlSessionTemplate,SqlSessionFactory屬性
  int resolvedAutowireMode = mbd.getResolvedAutowireMode();
  if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
      autowireByName(beanName, mbd, bw, newPvs);
    }
    if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
      // 獲取到依賴的bean並放到newPvs中
      autowireByType(beanName, mbd, bw, newPvs);
    }
    // 將新的屬性列表賦給舊的引用
    pvs = newPvs;
  }
}

autowireByName 和 autowireByType差不多,autowireByType更為複雜一些,這裡只分析autowireByType的處理過程

protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
	// 查詢非簡單(Java內建 基本型別,String,Date等)的屬性
  String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
  // 迴圈所有屬性名
  for (String propertyName : propertyNames) {
  	// 獲取方法引數
    MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
    // 構建一個依賴描述符
    DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
    // 獲取依賴的bean 
    // resolveDependency方法中呼叫了doResolveDependency,該方法我們在下一步的後置處理器呼叫中分析
		Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
    // 將bean放置到屬性集合中
    if (autowiredArgument != null) {
      pvs.add(propertyName, autowiredArgument);
    }
  }
}

現在,回到填充屬性的過程

該第六次呼叫後置處理器了,這一次主要對屬性和方法進行自動裝配

// CommonAnnotationBeanPostProcessor 處理@Resouce註解的裝配
// AutowiredAnnotationBeanPostProcessor 處理@Autowired @Value @Inject註解的裝配
for (BeanPostProcessor bp : getBeanPostProcessors()) {
  if (bp instanceof InstantiationAwareBeanPostProcessor) {
    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    // 處理自動裝配,將依賴的屬性裝配到bean中
    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    // ...省略已被廢棄的程式碼...
    pvs = pvsToUse;
  }
}

這一步的邏輯也是差不多,由於AutowiredAnnotationBeanPostProcessor複雜一些,我們取AutowiredAnnotationBeanPostProcessor中的邏輯進行分析

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
  // 取出之前postProcessMergedBeanDefinition時解析好的後設資料
  // @Autowired @Value @Inject 標識的屬性或方法
  // findAutowiringMetadata這裡有沒有和第四步中的很像呢~
  InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
  // 進行自動裝配
  metadata.inject(bean, beanName, pvs);
  return pvs;
}

findAutowiringMetadata,看看和第四步有多像吧~

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// 從快取中取出
		InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
		if (InjectionMetadata.needsRefresh(metadata, clazz)) {
			synchronized (this.injectionMetadataCache) {
				metadata = this.injectionMetadataCache.get(cacheKey);
				if (InjectionMetadata.needsRefresh(metadata, clazz)) {
					if (metadata != null) {
						metadata.clear(pvs);
					}
					// 構建後設資料,找到@Autowird @Value @Inject 標識的屬性或方法進行構建
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}

自動裝配過程

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) {
  // 取出之前去重過的後設資料列表
  Collection<InjectedElement> checkedElements = this.checkedElements;
  if (!elementsToIterate.isEmpty()) {
    for (InjectedElement element : elementsToIterate) {
      // 進行屬性或方法裝配
      element.inject(target, beanName, pvs);
    }
  }
}
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs){
  // 強轉成Field
  Field field = (Field) this.member;
  // 建立一個依賴描述符
  DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
  // 獲取到依賴的bean
	value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
  if (value != null) {
    ReflectionUtils.makeAccessible(field);
    // 將獲取到的依賴bean利用反射裝配到屬性中
    field.set(bean, value);
  }
}
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
  // 獲取bean
  result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
  return result;
}
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter){
  // 解析@Value註解
  Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
  if (value != null) {
  	return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
  }
  // 根據型別尋找是否有匹配的beanDefinition
	Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
  if (matchingBeans.isEmpty()) {
    // 為空則判斷是否必須
    if (isRequired(descriptor)) {
      // 必須則丟擲NoSuchBeanDefinitionException異常
      raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
    }
    return null;
  }
  // 如果根據型別匹配出來的候選bean不止一個,則需要確認是哪一個
  if (matchingBeans.size() > 1) {
    // 確認出真正需要依賴的
    // 先判斷是否有@Primary註解的
    // 沒有再判斷是否有實現了Priority註解的,取值最小的
    // 沒有最後使用屬性名進行匹配
    // 匹配不到則返回null
    autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    if (autowiredBeanName == null) {
      // 這裡進行確認是否必須,必須則丟擲異常
      if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
        return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
      }
      else {
        return null;
      }
    }
    instanceCandidate = matchingBeans.get(autowiredBeanName);
  }
  if (instanceCandidate instanceof Class) {
    // 呼叫getBean方法
    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
  }
  Object result = instanceCandidate;
  return result;
}

getBean方法

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {
  return beanFactory.getBean(beanName);
}

以上就是自動裝配的過程,再次回到填充屬性的方法,進行小小的收尾

// 如果不是xml byName byType 方式,其他方式pvs皆是空值
if (pvs != null) {
  // 呼叫set方法賦值
  applyPropertyValues(beanName, mbd, bw, pvs);
}
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
	// 使用反射給屬性賦值
  bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}

填充屬性過程,over~

初始化過程

initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd){
  // 如果bean實現了BeanNameAware,BeanClassLoaderAware,BeanFactoryAware介面
  // 則進行回撥相應的方法
  invokeAwareMethods(beanName, bean);
  // 第七次 在bean的初始化前進行處理
  // 呼叫@PostConstruct註解的方法,Aware介面的回撥方法
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  // 呼叫初始化方法
  // 如果bean實現了InitializingBean介面,則呼叫afterPropertiesSet方法
  // 如果bean還實現了自定義的初始化方法,也進行呼叫
  // 先afterPropertiesSet,再自定義
  invokeInitMethods(beanName, wrappedBean, mbd);
  // 第八次 處理初始化後的bean
  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

以上為初始化中的大概流程,接下來我們一個個分析

首先是invokeAwareMethods

private void invokeAwareMethods(String beanName, Object bean) {
  // 以下過程一目瞭然,就不過多分析了
  if (bean instanceof Aware) {
    if (bean instanceof BeanNameAware) {
      ((BeanNameAware) bean).setBeanName(beanName);
    }
    if (bean instanceof BeanClassLoaderAware) {
      ClassLoader bcl = getBeanClassLoader();
      if (bcl != null) {
        ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
      }
    }
    if (bean instanceof BeanFactoryAware) {
      ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    }
  }
}

applyBeanPostProcessorsBeforeInitialization

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName){
  Object result = existingBean;
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    // ImportAwareBeanPostProcessor處理ImportAware介面
    // InitDestroyAnnotationBeanPostProcessor處理@PostContrust註解
    // ApplicationContextAwareProcessor處理一系列Aware介面的回撥方法
    Object current = processor.postProcessBeforeInitialization(result, beanName);
    if (current == null) {
      return result;
    }
    result = current;
  }
  return result;
}

InitDestroyAnnotationBeanPostProcessor

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  // 取出在第四步解析@PostContrust @PreDestroy得到的後設資料
  LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
  // 呼叫init方法(@PostConstruct標識的)
  metadata.invokeInitMethods(bean, beanName);
  return bean;
}
public void invokeInitMethods(Object target, String beanName) throws Throwable {
  // 只取init的後設資料(還有destroy的)
  Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
  if (!initMethodsToIterate.isEmpty()) {
    for (LifecycleElement element : initMethodsToIterate) {
      element.invoke(target);
    }
  }
}
public void invoke(Object target) throws Throwable {
  ReflectionUtils.makeAccessible(this.method);
  // 直接反射呼叫
  this.method.invoke(target, (Object[]) null);
}

ApplicationContextAwareProcessor的過程和invokeAwareMethods的過程類似,這裡就不分析了

invokeInitMethods

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd){
  // 如果實現了InitializingBean介面,呼叫afterPropertiesSet方法
  boolean isInitializingBean = (bean instanceof InitializingBean);
  if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    ((InitializingBean) bean).afterPropertiesSet();
  }
  if (mbd != null && bean.getClass() != NullBean.class) {
    // 呼叫自定義的初始化方法
    String initMethodName = mbd.getInitMethodName();
    if (StringUtils.hasLength(initMethodName) &&
        !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
        !mbd.isExternallyManagedInitMethod(initMethodName)) {
      // 自定義init方法主要在@Bean註解進行宣告,取出beanDefinition中的initMethod呼叫就好了
      invokeCustomInitMethod(beanName, bean, mbd);
    }
  }
}

applyBeanPostProcessorsAfterInitialization

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {
  Object result = existingBean;
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    // Spring內建後置處理器中,只有ApplicationListenerDetector有處理邏輯
    // ApplicationListenerDetector會將實現了ApplicationListener介面的bean新增到事件監聽器列表中
    Object current = processor.postProcessAfterInitialization(result, beanName);
    if (current == null) {
      return result;
    }
    result = current;
  }
  return result;
}
public Object postProcessAfterInitialization(Object bean, String beanName){
  if (bean instanceof ApplicationListener) {
    // 將bean新增到事件監聽器列表中
    this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
  }
}

以上,bean初始化完畢!

伴隨著bean初始化完畢,bean就算建立完成了,本文也到此結束啦,有問題的小夥伴歡迎在下方留言喲~

下文預告:Spring原始碼分析之迴圈依賴

Spring 原始碼系列
  1. Spring原始碼分析之 IOC 容器預啟動流程(已完結)
  2. Spring原始碼分析之BeanFactory體系結構(已完結)
  3. Spring原始碼分析之BeanFactoryPostProcessor呼叫過程(已完結)
  4. Spring原始碼分析之Bean的建立過程(已完結)
  5. Spring原始碼分析之什麼是迴圈依賴及解決方案
  6. Spring原始碼分析之AOP從解析到呼叫
  7. Spring原始碼分析之事務管理(上),事物管理是spring作為容器的一個特點,總結一下他的基本實現與原理吧
  8. Spring原始碼分析之事務管理(下) ,關於他的底層事物隔離與事物傳播原理,重點分析一下
Spring Mvc 原始碼系列
  1. SpringMvc體系結構
  2. SpringMvc原始碼分析之Handler解析過程
  3. SpringMvc原始碼分析之請求鏈過程
Mybatis 原始碼系列

暫定


追更,可關注我,近期有時間就文章全寫完,分享純粹為了樂趣,也有一種成就感吧,筆者這篇文章先就到這

相關文章