//AbstractBeanFactory.java @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }複製代碼
實際調用的是 AbstractBeanFactory#doGetBean(String name, Class<T> requiredType,Object[] args, boolean typeCheckOnly) 方法,該方法接受四個參數:java
//AbstractBeanFactory.java protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { //<1> 返回 bean 名稱,剝離工廠引用前綴。 // 若是 name 是 alias ,則獲取對應映射的 beanName 。 final String beanName = transformedBeanName(name); Object bean; // 從緩存中或者實例工廠中獲取 Bean 對象 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } // <2> 完成 FactoryBean 的相關處理,並用來獲取 FactoryBean 的處理結果 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // <3> 由於 Spring 只解決單例模式下得循環依賴,在原型模式下若是存在循環依賴則會拋出異常。 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // <4> 若是當前容器中沒有找到,則從父類容器中加載 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); // 若是,父類容器爲 AbstractBeanFactory ,直接遞歸查找 if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); // 用明確的 args 從 parentBeanFactory 中,獲取 Bean 對象 } else if (args != null) { return (T)parentBeanFactory.getBean(nameToLookup, args); // 用明確的 requiredType 從 parentBeanFactory 中,獲取 Bean 對象 } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); // 直接使用 nameToLookup 從 parentBeanFactory 獲取 Bean 對象 } else { return (T)parentBeanFactory.getBean(nameToLookup); } } // <5> 若是不是僅僅作類型檢查則是建立bean,這裏須要記錄 if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // <6> 從容器中獲取 beanName 相應的 GenericBeanDefinition 對象,並將其轉換爲 RootBeanDefinition 對象 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 檢查給定的合併的 BeanDefinition checkMergedBeanDefinition(mbd, beanName, args); // <7> 處理所依賴的 bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 若給定的依賴 bean 已經註冊爲依賴給定的 bean // 即循環依賴的狀況,拋出 BeanCreationException 異常 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 緩存依賴調用 TODO 芋艿 registerDependentBean(dep, beanName); try { // 遞歸處理依賴 Bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // <8> bean 實例化 if (mbd.isSingleton()) { // 單例模式 sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // 顯式從單例緩存中刪除 Bean 實例 // 由於單例模式下爲了解決循環依賴,可能他已經存在了,因此銷燬它。 TODO 芋艿 destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // 原型模式 Object prototypeInstance; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { // 得到 scopeName 對應的 Scope 對象 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 { // 從指定的 scope 下建立 bean Object scopedInstance = scope.get(beanName, () -> { // 加載前置處理 beforePrototypeCreation(beanName); try { // 建立 Bean 對象 return createBean(beanName, mbd, args); } finally { // 加載後綴處理 afterPrototypeCreation(beanName); } }); // 從 Bean 實例中獲取對象 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; } } // <9> 檢查須要的類型是否符合 bean 的實際類型 if (requiredType != null && !requiredType.isInstance(bean)) { try { // 執行轉換 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); // 轉換失敗,拋出 BeanNotOfRequiredTypeException 異常 if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T)bean; }複製代碼
這段代碼很是長,並且邏輯超複雜,咱們將拆解這段代碼進行分析緩存
對應代碼段以下:markdown
//AbstractBeanFactory.java final String beanName = transformedBeanName(name);複製代碼
這裏的 name 不必定是 beanName,多是 aliasName,也有多是 FactoryBean,因此這裏須要調用 AbstractBeanFactory#transformedBeanName(String name) 方法,對 name 進行轉換。代碼段以下:ide
//AbstractBeanFactory.java protected String transformedBeanName(String name) { return canonicalName(BeanFactoryUtils.transformedBeanName(name)); }複製代碼
//BeanFactoryUtils.java //緩存已經轉換好的 name to beanName private static final Map<String, String> transformedBeanNameCache = new ConcurrentHashMap<>(); public static String transformedBeanName(String name) { Assert.notNull(name, "'name' must not be null"); if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { return name; } // name = "&userService" // beanName = "userService" return transformedBeanNameCache.computeIfAbsent(name, beanName -> { do { beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()); } while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)); return beanName; }); }複製代碼
//SimpleAliasRegistry.java //緩存 alias to beanName private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16); public String canonicalName(String name) { String canonicalName = name; String resolvedName; // 循環,從 aliasMap 中,獲取到最終映射的 beanName do { resolvedName = this.aliasMap.get(canonicalName); if (resolvedName != null) { canonicalName = resolvedName; } } while (resolvedName != null); return canonicalName; } 複製代碼
對應代碼段以下:post
//AbstractBeanFactory.java //從緩存或實例工廠中獲取 Bean 對象 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } // <x> 完成 FactoryBean 的相關處理,並用來獲取 FactoryBean 的處理結果 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }複製代碼
詳細解析,見 《【Spring 源碼】—— IoC 之加載 Bean:從單例緩存中獲取單》ui
對應代碼段以下:this
//AbstractBeanFactory.java //Spring 只處理單列模式下的循環依賴 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); }複製代碼
Spring 只處理單例模式下得循環依賴,對於原型模式的循環依賴直接拋出異常。主要緣由仍是在於,和 Spring 解決循環依賴的策略有關。
spa
詳細解析,見 《【Spring 源碼】—— IoC 之加載 Bean:parentBeanFactory 與依賴處理》
prototype
對應代碼段以下:
code
// AbstractBeanFactory.java // 若是當前容器中沒有找到,則從父類容器中加載 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); // 若是,父類容器爲 AbstractBeanFactory ,直接遞歸查找 if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly); // 用明確的 args 從 parentBeanFactory 中,獲取 Bean 對象 } else if (args != null) { return (T)parentBeanFactory.getBean(nameToLookup, args); // 用明確的 requiredType 從 parentBeanFactory 中,獲取 Bean 對象 } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); // 直接使用 nameToLookup 從 parentBeanFactory 獲取 Bean 對象 } else { return (T)parentBeanFactory.getBean(nameToLookup); } }複製代碼
若是當前容器中沒有相對應的 BeanDefinition 對象,則會嘗試從父容器中加載,而後遞歸調用 getBean(...) 方法。
詳細解析,見 《【Spring 源碼】—— IoC 之加載 Bean:parentBeanFactory 與依賴處理》
對應代碼段以下:
// AbstractBeanFactory.java // 若是不是僅僅作類型檢查則是建立bean,這裏須要記錄 if (!typeCheckOnly) { markBeanAsCreated(beanName); }複製代碼
詳細解析,見 《【Spring 源碼】—— IoC 之加載 Bean:parentBeanFactory 與依賴處理》
對應代碼段以下:
// AbstractBeanFactory.java // 從容器中獲取 beanName 相應的 GenericBeanDefinition 對象,並將其轉換爲 RootBeanDefinition 對象 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 檢查給定的合併的 BeanDefinition checkMergedBeanDefinition(mbd, beanName, args);複製代碼
..todo