<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] <br/> <br/> > ## `BeanFactory` `getBean(name)` ![](https://i.loli.net/2019/03/14/5c89f22fd5838.png) > ### `BeanFactory` ![](https://i.loli.net/2019/03/13/5c888d04acd85.png) * `BeanFactory` ``` public interface BeanFactory { //這里是對FactoryBean的轉義定義,因為如果使用bean的名字檢索FactoryBean得到的對象是工廠生成的對象 String FACTORY_BEAN_PREFIX = "&"; //這里根據bean的名字,在IOC容器中得到bean實例,這個IOC容器就是一個大的抽象工廠。 Object getBean(String name) throws BeansException; //這里根據bean的名字和Class類型來得到bean實例,和上面的方法不同在于它會拋出異常:如果根據名字取得的bean實例的Class類型和需要的不同的話。 <T> T getBean(String name, Class<T> requiredType); <T> T getBean(Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; //這里提供對bean的檢索,看看是否在IOC容器有這個名字的bean boolean containsBean(String name); //這里根據bean名字得到bean實例,并同時判斷這個bean是不是單件 boolean isSingleton(String name) throws NoSuchBeanDefinitionException; //這里根據bean名字得到bean實例,并同時判斷這個bean是不是原型 boolean isPrototype(String name) throws NoSuchBeanDefinitionException; //這里對得到bean實例的Class類型 Class<?> getType(String name) throws NoSuchBeanDefinitionException; //這里得到bean的別名,如果根據別名檢索,那么其原名也會被檢索出來 String[] getAliases(String name); } ``` * `HierarchicalBeanFactory`,是為了實現bean工廠的層級關系提供支持,其中聲明兩個方法 ``` //得到父工廠 BeanFactory getParentBeanFactory(); //在本地工廠中有沒有給定名稱的bean,不包括繼承的工廠 boolean containsLocalBean(String name); ``` <br/> > ### `getBean()` ``` public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { // beanName轉換 1、移除&開頭的字符 2、處理alis別名 final String beanName = transformedBeanName(name); Object bean; //從bean的實例緩存中獲取,singletonObjects緩存,map結構 Map<beanName, beanInstance> Object sharedInstance = getSingleton(beanName); // sharedInstance = null,緩存里還沒有對應的實例,表明這個實例還沒創建。 // BeanFactory 并不會在一開始就將所有的單例 bean 實例化好,而是在調用 getBean 獲取時再實例化,懶加載 // ApplicatioContext會在spring啟動時先將所有的bean都加載好 // getBean 方法有很多重載,比如 getBean(String name, Object... args) // BeanFactory 會根據這些參數 args 去匹配合適的構造方法構造 bean 實例。 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 + "'"); } } //如果 sharedInstance 是普通的單例 bean,下面的方法會直接返回 //如果sharedInstance 是 FactoryBean 類型的,則需調用 getObject 工廠方法獲取真正的bean 實例 //如果用戶想獲取 FactoryBean 本身,這里也不會做特別的處理,直接返回 //FactoryBean 的實現類本身也是一種 bean。 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } /* * 如果上面的條件不滿足,則表明 sharedInstance 可能為空,此時 beanName 對應的 bean * 實例可能還未創建。這里還存在另一種可能,如果當前容器有父容器,beanName 對應的 bean 實例 * 可能是在父容器中被創建了,所以在創建實例前,需要先去父容器里檢查一下。 */ else { //如果上面的條件不滿足,則表明 sharedInstance 可能為空,此時 beanName 對應的 bean還未創建 //還存在另一種可能,如果當前容器有父容器,beanName 對應的 bean 實例 可能在父容器中創建了 //所以需要檢查一下父容器 // BeanFactory 不緩存 Prototype 類型的 bean,無法處理該類型 bean 的循環依賴問題 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 如果 sharedInstance = null,則到父容器中查找 bean 實例 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 獲取 name 對應的 beanName,如果 name 是以 & 字符開頭,則返回 & + beanName String nameToLookup = originalBeanName(name); // 根據 args 是否為空,以決定調用父容器哪個方法獲取 bean if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // 合并父 BeanDefinition 與子 BeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 檢查是否有 dependsOn 依賴,如果有則先初始化所依賴的 bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { //檢測是否存在 depends-on 循環依賴 //depends-on 循環,Spring 會直接 拋出異常 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 注冊依賴記錄 registerDependentBean(dep, beanName); try { // 加載 depends-on 依賴 getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 創建 bean 實例 if (mbd.isSingleton()) { /* * 這里并沒有直接調用 createBean 方法創建 bean 實例,而是通過 * getSingleton(String, ObjectFactory) 方法獲取 bean 實例。 * getSingleton(String, ObjectFactory) 方法會在內部調用 * ObjectFactory 的 getObject() 方法創建 bean,并會在創建完成后, * 將 bean 放入緩存中。關于 getSingleton 方法的分析,本文先不展開,我會在 * 后面的文章中進行分析 */ sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { // 創建 bean 實例 return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); // 如果 bean 是 FactoryBean 類型,則調用工廠方法獲取真正的 bean 實例。否則直接返回 bean 實例 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 創建 prototype 類型的 bean 實例 else if (mbd.isPrototype()) { Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } // 創建其他類型的 bean 實例 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>() { @Override public 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()); } } // 返回 bean return (T) bean; } ``` > ### `beanName`轉換 * 處理以字符 `&` 開頭的 `name`,處理別名。 ``` protected String transformedBeanName(String name) { // 這里調用了兩個方法: // BeanFactoryUtils.transformedBeanName(name) 處理&字符 //canonicalName 轉換別名 return canonicalName(BeanFactoryUtils.transformedBeanName(name)); } ``` <br/> > ### 從緩存中獲取`bean`實例。 * 對于單例`bean`,`Spring`容器只會實例化一次。后續再次獲取時,只需直接從緩存里獲取即可,無需且不能再次實例化。 * 從緩存中取`bean`實例的方法是`getSingleton(String)`。 ``` public Object getSingleton(String beanName) { return getSingleton(beanName, true); } // allowEarlyReference表示是否允許其他 bean 引用正在創建中的 bean,用于處理循環引用的問題。 protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 從 singletonObjects 獲取實例,singletonObjects 中緩存的實例都是完全實例化好的 bean,可以直接使用 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 從 earlySingletonObjects 中獲取提前曝光的 bean,用于處理循環引用 singletonObject = this.earlySingletonObjects.get(beanName); // 如果如果 singletonObject = null,且允許提前曝光 bean 實例,則從相應的 ObjectFactory 獲取一個原始的(raw)bean(尚未填充屬性) if (singletonObject == null && allowEarlyReference) { // 獲取相應的工廠類,獲取對應beanName的工廠類 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 提前曝光 bean 實例,用于解決循環依賴 //此處為實際創建bean實例 singletonObject = singletonFactory.getObject(); // 放入上級緩存,如果還有其他 bean 依賴當前 bean,其他 bean 可以直接從 earlySingletonObjects 取結果 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); } ``` * 其中涉及了三個緩存 ![](https://i.loli.net/2019/03/12/5c87952a56166.png) <br/> > ### 合并父 BeanDefinition 與 子 BeanDefinition * `Spring` 支持配置繼承,在標簽中可以使用`parent`屬性配置父類 `bean`。這樣子類 `bean` 可以繼承父類 `bean` 的配置信息,同時也可覆蓋父類中的配置。比如下面的配置: ``` <bean id="hello" class="xyz.coolblog.innerbean.Hello"> <property name="content" value="hello"/> </bean> <bean id="hello-child" parent="hello"> <property name="content" value="I`m hello-child"/> </bean> ``` <br/> > ### 從 `FactoryBean` 中獲取 `bean` 實例 * 單例類型,將`FactoryBean`生成的`bean`放入緩存 * 非單例,每次創建新的`bean` *** > ### 參考 #### [Spring IOC 容器源碼分析 - 循環依賴的解決辦法](https://segmentfault.com/a/1190000015221968) #### [Spring IOC 容器源碼分析 - 獲取單例 bean](http://www.tianxiaobo.com/2018/06/01/Spring-IOC-%E5%AE%B9%E5%99%A8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E8%8E%B7%E5%8F%96%E5%8D%95%E4%BE%8B-bean/) #### [Spring IOC 容器源碼分析系列文章](http://www.tianxiaobo.com/2018/05/30/Spring-IOC-%E5%AE%B9%E5%99%A8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0%E5%AF%BC%E8%AF%BB/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看