做者:小傅哥
博客:https://bugstack.cnhtml
沉澱、分享、成長,讓本身和他人都能有所收穫!😄
你提出問題,就要給出解決方案!
java
最近有粉絲小夥伴反饋,與本身的上級溝通老是遇到障礙,感受不被理解。大部分時候他提出來的事情均可能會被領導說:「我沒get到你的點」、「你想作的這個項目沒有業務價值」、「你提出問題,就要給出解決方案」,等等諸如此類的回答。程序員
鑑於具體狀況要具體分析,可能咱們並不必定能判斷出是誰的問題,致使在每次的交談中出現的分歧。多是leader有leader的苦衷和視角,也多是員工有員工的理解和想法,因此最終沒有達成一致。面試
但就帶團隊來說,有效溝通很重要。就像:若是你說的都對,那我爲何和你爭吵呢?與其壓制遇到的矛盾點,不如都攤開了聊,誰的視角和心胸更大,誰就多有一些同理心。spring
若是尖銳的批評徹底消失,溫和的批評將會變得刺耳。編程
若是溫和的批評也不被容許,沉默將被認爲居心叵測。緩存
若是沉默也再也不容許,讚賞不夠賣力將是一種罪行。網絡
若是隻容許一種聲音存在,那麼,惟一存在的那個聲音就是謊話。ide
謝飛機,小記!
,總感受 Spring 也沒啥看的,怎麼面試官一問就能問出花?函數
面試官:Spring 的 getBean 中,transformedBeanName 的做用是什麼?
謝飛機:不知道呀,看單詞意思好像是改變Bean名稱。
面試官:那這麼說,你的 Bean 若是有 alias 別名,Spring 在獲取 Bean 時候要怎麼處理?
謝飛機:這!
面試官:那若是用了 depends-on 呢?
謝飛機:啊, 我沒用過 depends-on 我不知道!
面試官:那你調試代碼時候,看見過BeanName前面有 & 的狀況嗎,爲啥會出現?
謝飛機:我不配知道!再見!
對於剛接觸看 Spring 源碼的夥伴來講,可能很疑惑於怎麼就獲取一個 Bean 就這麼多流程呢?
因此,它爲了適應各種的需求,變得愈來愈複雜了。而這部分知識的深刻學習絕對不僅是爲了應付八股文,更多的是考慮到在平常的 Spring 使用中遇到複雜問題時有沒有一個大體知曉的流程,能夠快速定位問題,以及此類需求的技術實現方案是否能在之後的應用開發中起到必定的指導做用,由於它是一種設計方案的具體實現。
圖稿
,獲取。接下來,咱們就依次的把關於獲取 Bean 實例的重點代碼列舉出來作分析,讀者夥伴也能夠結合流程圖一塊兒看,這樣會更方便理解。
@Test public void test_getBean() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml"); UserDao userDao = beanFactory.getBean("userDao", UserDao.class); logger.info("獲取 Bean:{}", userDao); }
beanFactory.getBean
的方式去獲取一個 Bean 實例。源碼位置:AbstractBeanFactory -> getBean() -> doGetBean()
@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、處理帶&符的工廠BeanName final 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 是以 & 開頭,則返回 & + beanName String 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,轉換爲 RootBeanDefinition final 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>() { @Override public Object getObject() throws BeansException { try { // 建立 bean return 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>() { @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; }
綜上基本就是 getBean 過程涉及到的核心處理方法,基本包括;
處理 & 符:transformedBeanName() -> BeanFactoryUtils.transformedBeanName(name)
public static String transformedBeanName(String name) { Assert.notNull(name, "'name' must not be null"); String beanName = name; while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()); } return beanName; }
(String FACTORY_BEAN_PREFIX = "&")
&&&userService -> &&userService -> &userService -> userService
別名轉換:transformedBeanName() -> canonicalName
public String canonicalName(String name) { String canonicalName = name; // Handle aliasing... String resolvedName; do { resolvedName = this.aliasMap.get(canonicalName); if (resolvedName != null) { canonicalName = resolvedName; } } while (resolvedName != null); return canonicalName; }
<bean id="userService" class="org.itstack.interview.UserService"/> <alias name="userService" alias="userService-alias01"/> <alias name="userService-alias01" alias="userService-alias02"/>
AbstractBeanFactory -> isDependent(beanName, dep) -> DefaultSingletonBeanRegistry
protected boolean isDependent(String beanName, String dependentBeanName) { synchronized (this.dependentBeanMap) { return isDependent(beanName, dependentBeanName, null); }
<bean id="userService" class="org.itstack.interview.UserService" depends-on="userDao"/> <bean id="userDao" class="org.itstack.interview.UserDao"/>
private boolean isDependent(String beanName, String dependentBeanName, Set<String> alread if (alreadySeen != null && alreadySeen.contains(beanName)) { return false; } String canonicalName = canonicalName(beanName); 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<String>(); } alreadySeen.add(beanName); if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) { return true; } } return false; }
AbstractBeanFactory -> registerDependentBean(dep, beanName) -> DefaultSingletonBeanRegistry
public void registerDependentBean(String beanName, String dependentBeanName) { String canonicalName = canonicalName(beanName); synchronized (this.dependentBeanMap) { Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans == null) { dependentBeans = new LinkedHashSet<String>(8); this.dependentBeanMap.put(canonicalName, dependentBeans); } dependentBeans.add(dependentBeanName); } synchronized (this.dependenciesForBeanMap) { Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName if (dependenciesForBean == null) { dependenciesForBean = new LinkedHashSet<String>(8); this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean); } dependenciesForBean.add(canonicalName); } }
最後:getBean(dep),就能夠獲取到 depends-on 依賴的 Bean 了
AbstractBeanFactory -> mbd.isSingleton()
if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "'beanName' must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<Exception>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return (singletonObject != NULL_OBJECT ? singletonObject : null); } }
doCreateBean -> if (earlySingletonExposure) -> getSingleton(beanName, false)
protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 從 singletonObjects 獲取實例,singletonObjects 中緩存的實例都是徹底實例化好的 bean,能夠直接使用 Object singletonObject = this.singletonObjects.get(beanName); // 若是 singletonObject 爲空,則沒有建立或建立中 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 加鎖 synchronized (this.singletonObjects) { // 單例緩存池中,沒有當前beanName singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 加入到三級緩存,暴漏早期對象用於解決三級緩存 singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); }
singletonFactories,用於存放 bean 工廠,bean 工廠所生成的 bean 尚未完成初始化 bean。
AbstractBeanFactory -> getObjectForBeanInstance(sharedInstance, name, beanName, null)
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { // 若是 beanName 以 & 開頭,但 beanInstance 卻不是 FactoryBean,則會拋出異常 if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } // 這裏判斷就是這個 bean 是否是 FactoryBean,不是就直接返回了 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null; if (mbd == null) { // 若是 mbd 爲空,則從緩存加載 bean(FactoryBean 生成的單例 bean 實例會緩存到 factoryBeanObjectCache 集合中,方便使用) object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // 到這,beanInstance 是 FactoryBean 類型,因此就強轉了 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // mbd 爲空且判斷 containsBeanDefinition 是否包含 beanName if (mbd == null && containsBeanDefinition(beanName)) { // 合併 BeanDefinition mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); // 調用 getObjectFromFactoryBean 獲取實例 object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }
<bean id="userService" class="org.itstack.interview.UserService"/> <!-- 起個別名 --> <alias name="userService" alias="userService-alias01"/> <!-- 別名的別名 --> <alias name="userService-alias01" alias="userService-alias02"/>
@Test public void test_alias() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-alias.xml"); UserService userService = beanFactory.getBean("userService-alias02", UserService.class); logger.info("獲取 Bean 經過別名:{}", userService); }
<bean id="userService" class="org.itstack.interview.UserService" depends-on="userDao"/> <bean id="userDao" class="org.itstack.interview.UserDao"/>
@Test public void test_depends_on() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-depends-on.xml"); UserService userService = beanFactory.getBean(UserService.class, "userService"); logger.info("獲取 Bean:{}", userService.getUserDao()); }
<bean id="userDao" class="org.itstack.interview.MyFactoryBean"/>
@Test public void test_factory_bean() { BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-factory-bean.xml"); UserDao userDao = beanFactory.getBean("userDao", UserDao.class); logger.info("獲取 Bean:{}", userDao); }