nginx源碼解析,Spring的getBean的流程(源碼級講解 + 核心流程總結)

 2023-11-19 阅读 41 评论 0

摘要:如果你正打算深入學習Spring,但是不知從何學起,那么我強烈推薦你可以按照這個系列做一遍。本系列將Spring框架的各個部分從它龐雜的代碼體系中抽取出來,然后對每一個部分進行講解,并最終搭建成簡易版Spring。我以人格保證:如果你可以堅持
如果你正打算深入學習Spring,但是不知從何學起,那么我強烈推薦你可以按照這個系列做一遍。本系列將Spring框架的各個部分從它龐雜的代碼體系中抽取出來,然后對每一個部分進行講解,并最終搭建成簡易版Spring。我以人格保證:如果你可以堅持做下來,那么你對Spring這塊的知識就基本都掌握清楚了! 附上該系列地址:https://blog.csdn.net/zhang_qing_yun/article/details/120084497
# getBean的流程 ## 源碼
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException { // getBean 其實沒做啥,都在 doGetBean 里return doGetBean(name, requiredType, null, false);
}
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {     // 處理別名BeanName、處理帶&符的工廠BeanNamefinal String beanName = transformedBeanName(name);Object bean;  // 先嘗試從緩存中獲取Bean實例,這個位置就是三級緩存解決循環依賴的方法Object sharedInstance = getSingleton(beanName);   if (sharedInstance != null && args == null) {if (logger.isDebugEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.debug("Returning cached instance of singleton bean '" + beanName + "'");}}        // 1. 如果 sharedInstance 是普通的 Bean 實例,則下面的方法會直接返回// 2. 如果 sharedInstance 是工廠Bean類型,則需要獲取 getObject 方法,可以參考關于 FactoryBean 的實現類 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// 循環依賴有三種,setter注入、多實例和構造函數,Spring 只能解決 setter 注入,所以這里是 Prototype 則會拋出異常if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}    // 1. 父 bean 工廠存在// 2. 當前 bean 不存在于當前bean工廠,則到父工廠查找 bean 實例BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// 獲取 name 對應的 beanName,如果 name 是以 & 開頭,則返回 & + beanNameString nameToLookup = originalBeanName(name);         // 根據 args 參數是否為空,調用不同的父容器方法獲取 bean 實例if (args != null) {return (T) parentBeanFactory.getBean(nameToLookup, args);}else {return parentBeanFactory.getBean(nameToLookup, requiredType);}}       // 1. typeCheckOnly,用于判斷調用 getBean 方法時,是否僅是做類型檢查// 2. 如果不是只做類型檢查,就會調用 markBeanAsCreated 進行記錄if (!typeCheckOnly) {markBeanAsCreated(beanName);}try {    // 從容器 getMergedLocalBeanDefinition 獲取 beanName 對應的 GenericBeanDefinition,轉換為 RootBeanDefinitionfinal RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 檢查當前創建的 bean 定義是否為抽象 bean 定義checkMergedBeanDefinition(mbd, beanName, args);// 處理使用了 depends-on 注解的依賴創建 bean 實例String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {   // 監測是否存在 depends-on 循環依賴,若存在則會拋出異常if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}       // 注冊依賴記錄registerDependentBean(dep, beanName);try {    // 加載 depends-on 依賴(dep 是 depends-on 縮寫)getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}  // 創建單例 bean 實例if (mbd.isSingleton()) {    // 把 beanName 和 new ObjectFactory 匿名內部類傳入回調sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {try {    // 創建 beanreturn createBean(beanName, mbd, args);}catch (BeansException ex) {// 創建失敗則銷毀destroySingleton(beanName);throw ex;}}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}      // 創建其他類型的 bean 實例else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; consider " +"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// 如果需要類型轉換,這里會進行操作if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {try {return getTypeConverter().convertIfNecessary(bean, requiredType);}catch (TypeMismatchException ex) {if (logger.isDebugEnabled()) {logger.debug("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}    // 返回 Beanreturn (T) bean;
}

幾個重要函數:

	protected String transformedBeanName(String name) {//如果beanName是以&開頭的  則截取掉開頭的&return canonicalName(BeanFactoryUtils.transformedBeanName(name));}public String canonicalName(String name) {String canonicalName = name;// 循環的去獲取別名,直到獲取到真實的beanName//aliasA->aliasB->beanNameString resolvedName;do {resolvedName = this.aliasMap.get(canonicalName);if (resolvedName != null) {canonicalName = resolvedName;}}while (resolvedName != null);return canonicalName;}
	protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {//如果name是以&開頭的 但是不是FactoryBean,則直接拋出異常if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());}// 則beanInstance可能是一個普通的bean,也可能是一個FactoryBean// 如果是一個普通的bean,則直接返回if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {return beanInstance;}//FactoryBean創建出bean實例返回Object object = null;if (mbd == null) {object = getCachedObjectForFactoryBean(beanName);}if (object == null) {FactoryBean<?> factory = (FactoryBean<?>) beanInstance;if (mbd == null && containsBeanDefinition(beanName)) {mbd = getMergedLocalBeanDefinition(beanName);}boolean synthetic = (mbd != null && mbd.isSynthetic());object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;}

流程總結

getBean核心流程圖

  1. 調用transformedBeanName函數處理Bean的名字,主要有兩個目的:一是對FactoryBean的Name做一些處理(通常FactoryBean的名字前面會增加一個&符號用來和普通Bean的BeanName區分,但是在存儲上沒有差異),另一個是針對別名的處理,將其替換為真實的BeanName。
  2. 調用getSingleton函數從三級緩存中搜索要查找的Bean:
    1. 如果不為null,則說明已經創建過或者正在創建中(循環依賴就是在這里解決的)。這時如果獲取到的Bean是普通Bean就會直接返回,getBean流程結束。如果獲取到的是FactoryBean,則會先去緩存中查找該BeanName對應的FactoryBean是否生產過對象,如果有則直接返回,getBean流程結束;如果緩存中獲取不到,說明該FactoryBean還沒有生產過對象,則會調用該FactoryBean的getObject方法去生產一個Bean,然后將這個工廠Bean創造的Bean添加到緩存中(注意:這里的緩存并不是三級緩存中的任何一個,而是一個專門用于存放工廠Bean即FactoryBean創造出來的Bean的緩存,位于FactoryBeanRegistrySupport中,也就是說,FactoryBean存放于三級緩存中,它創造出來的Bean并不在三級緩存中,兩者沒有被緩存在同一個地方),然后將生產出來的Bean返回,getBean流程結束。nginx源碼解析,
    2. 如果從緩存中獲取到null,如果當前工廠的父工廠存在且當前工廠中沒有該Bean的定義信息的話,就會去到父工廠中去執行getBean操作(這時如果創建對象也會保存在父工廠中),然后直接返回父工廠getBean的結果,getBean流程結束。如果沒有父工廠或者當前工廠中存在該Bean的定義信息,就會去創建該Bean:首先,獲取Bean的定義信息。然后處理該Bean通過@DependsOn注解指定的Bean(通過該注解可以指定Bean的加載順序,優先加載指定的Bean),遍歷這些指定的Bean的名字,調用getBean函數完成對這些Bean的加載。然后執行beforeSingletonCreation方法,將該Bean標記成正在創建狀態;然后會去執行createBean方法的邏輯(詳細解析可以看:創建Bean的流程);執行afterSingletonCreation方法,將bean從正在創建的狀態中移除;然后調用addSingleton方法,將該Bean添加到一級緩存中,并刪除它在二、三級緩存中的內容。Bean創建完成后,會去執行getObjectForBeanInstance方法,作用是如果該Bean是FactoryBean類型,就會去獲取該FactoryBean要創造的對象,然后將其作為最終的對象并返回(注意:這里的創建邏輯是單例Bean的)。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/181983.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息