上篇博文中咱們看到了將Spring環境中的 BeanPostProcessor找出來,添加到BeanFactory中的beanPostProcessors中,統一維護,本片博文繼續往下拓展,看下Spring如何實例化bean,以及如何實如今bean的實例化經過各類各樣的後置處理器完成bean的加強java
因此本次的程序入口是AbstractApplicationContext
中的finishBeanFactoryInitialization(beanFactory);
,源碼以下,主要作了以下幾件事程序員
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. // 爲上下文初始化類型轉換器 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // 檢查上下文中是否存在類型轉換器 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // 儘早初始化LoadTimeWeaverAware bean,以便儘早註冊它們的轉換器。 // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. // 禁止使用臨時類加載器進行類型匹配 beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes // 容許緩存全部的bean的定義數據 beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. // 準備實例化bean beanFactory.preInstantiateSingletons(); }
咱們着重看他是如何建立實例化bean的,跟進beanFactory.preInstantiateSingletons();
,調用beanFactory的方法準備實例化bean, 這個beanFactory就是Spring默認是bean工廠, DefaultListableBeanFactory
, 源碼以下:方法不算很長,邏輯也很清楚, 一開始Spring取出當前上下文中全部的BeanName列表,由於在執行到這裏以前,已經完成包掃描了因此說這個盛放beanName的list裏面存放的就是全部的須要實例化的對象的全集,包含Spring本身的,和程序員本身添加的還包含Aspectj的spring
因此說,當前方法的目標很明瞭,就是遍歷這個list中的每個beanName,而後實例化當前beanName相應的beanbootstrap
固然,若是想實例化,前提是不能是抽象類,不能是接口,非懶加載, 並且針對FactoryBean
還有不一樣的處理模式緩存
public void preInstantiateSingletons() throws BeansException { if (logger.isDebugEnabled()) { logger.debug("Pre-instantiating singletons in " + this); } //全部bean的名字 // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. //todo 遍歷一個副本以容許init方法,而init方法反過來註冊新的bean定義。 // todo 盛放全部的beanName,全部的須要實例化的beanName都在這裏,包括Spring斷斷續續添加的, Aspectj的, 程序員經過註解標識的 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... // todo 觸發全部非延遲加載單例beans的初始化,主要步驟爲調用getBean for (String beanName : beanNames) { // todo 合併父類BeanDefinition,能夠進入查看 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //todo 三個條件,抽象,單例,非懶加載 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); // todo 若是是FactoryBean則加上& // todo 檢驗是不是 FactoryBean 類型的對象 if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { // todo 由於咱們沒有添加FactoryBean類型的對象, 通常都會進入這個getBean getBean(beanName); } } }
下面接着跟進getBean(beanName);
方法,顧名思義獲取Bean,再往下跟下去,就算是本文的正文開始部分了,可是我想在這裏級具體一下,一個比較有份量的劇透吧,當前的getBean(beanName)
它是有返回值的,一會當咱們往下跟進的是時候會發現會存在遞歸的現象,這一點巧妙的實現了@Autowired
處理setter方式實現循環引用數據結構
ok,如今繼續看代碼,通過了幾個空方法的傳遞,咱們來到下面的代碼中,它主要作了以下幾件事app
首先將傳遞進來的name轉換成了beanName框架
緣由1: FactoryBean的實現類的存儲方式和其餘的類徹底相同,添加上&是獲取不到的, 所以咱們將&去掉 緣由2: 解決別名的問題ide
爲何在建立bean以前先調用getSingleton()
?函數
回想一下,如今是Spring啓動的過程當中,是在準備實例化bean,爲何一開始就來getSingleton()
,跟進源碼查看這個方法,它最終實現中有一行代碼是這樣的Object singletonObject = this.singletonObjects.get(beanName);
而這個singletonObjects
就是微觀層面的IOC容器,循環建立剛開始時,IOC確實是空的,可是我前面存在劇透,一開始的getBean()
方法是存在遞歸調用現象的,直接舉2個例子: 第一:假如如今在實例化A,結果有發現須要給A注入B, 那Spring是否是得得到B,怎麼得到呢? 遞歸使用getBean(BName)
完成, 第二個例子: A被添加上了@Lazy註解,是懶加載的,可是終究有一個會經過getBean(AName)
獲取A,這是發現A是實例化須要B,B確定已經實例化完事了,一樣是經過遞歸getBean(BName)
實現注入, 在這兩個過程當中就是getSingleton()
保證不會重複建立已經存在的實例
咱們關注的重點實際上是第二個getSingleton(beanName()->{xxx})
在第二個getSingleton()
方法中才是真正的去實例化bean的方法
最後,在當前的方法最後將bean返回了
前面我就是說過了,getBean(beanName)
存在遞歸調用的狀況,爲何我會一直說這個事呢,由於若是不知道這個事的話,這些代碼看起來是沒有頭緒的,可是明白這個事,看代碼就變得頗有邏輯,我在簡單總結一下怎個玩這個遞歸呢? 假設如今經過getBean(AName)
來注入A對象,可是呢發現了A依賴B對象,因而在getBean(AName)
裏面調用getBean(BName)
,經過這個方法返回出B對象完成A的注入
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 將傳遞進來的name final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. // 及早的檢查一下有沒有已經註冊了的單例對象 Object sharedInstance = getSingleton(beanName);// todo ::: name=myService時,此次來調用的就是 DefaultSingletonBeanRegistry中的 getSingleton() , 不一樣之處是多傳遞了一個true if (sharedInstance != null && args == null) { // 若是存在的話,將其取出賦值給bean,後續直接返回這個bean bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. // 來到這裏就說明要獲取的bean尚未實例化過 // 因而檢驗一下,若是是原形,直接拋異常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. // 檢查是否存在默認的父工廠 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { // 將當前的beanName存放到AlreadeyCreated這個set集中,標識這個bean被建立了 markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. // 確保當前bean所依賴的bean都已經初始化好了 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. if (mbd.isSingleton()) { // 實例化bean sharedInstance = getSingleton(beanName, () -> { // 真正的完成bean的建立 return createBean(beanName, mbd, args); }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 下面是進行其餘的檢查工做,這裏再也不深究了 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, () -> { 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; } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } 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()); } } return (T) bean; }
通過了上面一頓扯,而後咱們繼續往下跟,看看createBean(beanName, mbd, args)
方法中是如何實例化咱們的Bean的, 上面的方法是在AbstractBeanFactory
中,createBean(beanName, mbd, args)
是它的抽象方法, 那實現類是哪一個呢?
AbstractAutowireCapableBeanFactory
,隆重的誇一下這個類,Spring都稱讚這個類是有有才華的
在這個方法中,主要作了兩件事:兩件大事!!!
第一件大事:
在實例化Bean前,第一次調用後置處理器, 這件大事絕對是有歷史意義的!!!爲啥呢?你們想一想,bean尚未建立呢!就已經能夠插手bean的建立過程了,不是很刺激嗎?接着看回調了什麼後置處理器呢? Spring會循環全部的處理器檢查當前被遍歷的處理器是不是InstantiationAwareBeanPostProcessor
類型的,若是是的話呢,就執行這個後置處理器的postProcessBeforeInstantiation(beanClass, beanName);
方法
這個postProcessBeforeInstantiation()
是容許有返回值的,你們能夠想一想,這一點是否是有點可怕? 事實也是這樣,後置處理器的目的是爲了加強對象,而咱們卻能夠在這裏返回一個任何東西,狸貓換臺子替換掉原始的,尚未被建立的對象,還有一點,就是一旦咱們在這裏真的是沒有返回null,那後續Spring就沒有義務在去爲咱們建立原本應該建立的對象了,代碼經過if-else的選擇分支會使得當前的對象再也不經歷其餘後置處理器的加強,最終執行它父類的postProcessorAfterInitialization()
補充一點,咱們經過@EnableAspectjAutoProxy添加到Spring上下文中的AnnotationAwareAspectjAutoProxyCreator
對象其實就是這個類型InstantiationAwareBeanPostProcessor
,也就是說在這裏這個接口的相關方法會被回調,下面看看他的實現類AbstractAutoProxyCreator
對這個before()
方法的重寫實現,源碼以下:
主要邏輯就是找出須要產生代理加強的bean(切面類),和普通的bean, 須要加強的bean放在advisedBeans
裏面,由於須要加強的bean是須要動態植入其餘邏輯的,因此不放在一塊兒
判斷當前bean是不是基礎類型的,好比: Advice PointCut Advisor AopInfrastructureBean 或者是 切面Aspectj 都算是基礎類型,標註這些信息的類,是不會被加強的,標記false
主意啊,上面說的都是做用都是進行了一下標記
//todo 跟進來 @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } // todo 亮點就是在這裏, 若是是咱們切面類來到這裏,條件是知足的 // todo advicedBeans 見名知意: 通知beans // todo Spring用它標識, 被放在這個方法中的類,所有都不會被加強 // todo 知足什麼條件時,經過檢查呢? 就是檢查是否標記有 @Aspectj @Before ... 等註解 // todo 說的再直接一點, 就是返回了null, 表示當前的切面仍然須要按照正常的流程建立出來,可是這裏進行標記了 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // Create proxy here if we have a custom TargetSource. todo 若是咱們有一個自定義的TargetSource,在這裏建立代理 // Suppresses unnecessary default instantiation of the target bean: // todo 抑制沒必要要的目標bean的默認實例化: // The TargetSource will handle target instances in a custom fashion. todo TargetSource將以自定義方式處理目標實例。 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null; }
通過上面的標記,在哪裏產生的代理對象呢?實際上是在AbstractAutowireCapeableBeanFactory
中的initializeBean()
方法中實現的postProcessAfterInitialization()
實現的,在本文的末尾展開討論
第二件大事: 實例化對象, 繼續跟進
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class which cannot be stored in the shared merged bean definition. // todo 作各類各樣的屬性值的賦值, 好比這種 經過Spring的Bean傳遞給Spring框架的值 ==> bd.setPropertyValue("aaa") Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. // todo 處理 lookup-method 和 replace-method 配置,Spring 將這兩個配置統稱爲 override method try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // todo 在實例化以前完成一次解析操做,這也是 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { //todo 調用 doCreateBean 建立bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } }
咱們繼續跟進doCreateBean(beanName, mbdToUse, args);
方法, 一樣是本類AbstarctAutowireCapableBeanFactory
的方法,源碼以下: 這個方法也是無與倫比的重要,那這個方法中作了什麼事情呢?以下
由於這個方法簡直過重要了,上面列舉的每一點都值得咱們仔細分析,咱們每一條的分析都寫在下面代碼的下面
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. // todo BeanWrapper 用來包裝bean BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { // todo 一開始 factoryBeanInstanceCache 這個map中是沒有值的, 因此進入下面的if instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } // todo !!!!!!!!這裏獲取出來的對象是原生對象!!!!!!!!!!!! final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; // todo 到目前爲止仍是原生對象 //todo 用來填充屬性 //設置屬性,很是重要 populateBean(beanName, mbd, instanceWrapper); // todo 通過AOP處理,原生對象轉換成了代理對象,跟進去 //執行後置處理器,aop就是在這裏完成的處理 exposedObject = initializeBean(beanName, exposedObject, mbd); return exposedObject; }
實例化對象
我把源碼貼在了下面,下面方法的目的就是選出一個策略來實例化一個對象, 那有什麼策略呢? 這就看程序員是怎麼配置的了, 程序員能夠配置工廠方法,指定構造方法,或者是程序員沒有作出任何干涉,讓Spring按本身的方式去實例化
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // Make sure bean class is actually resolved at this point. Class<?> beanClass = resolveBeanClass(mbd, beanName); /** * todo 檢測一個類的訪問權限, Spring默認是 容許訪問非public類型的方法 */ if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } /** * 建立一個bean的快捷方式 */ boolean resolved = false; boolean autowireNecessary = false; // todo 是不是必須自動裝配 if (args == null) { synchronized (mbd.constructorArgumentLock) { // todo if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; //若是已經解析了構造方法的參數,則必需要經過一個帶參構造方法來實例 autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) {// todo 若是是須要自動注入的,就使用構造方法自動注入 // 經過構造方法自動裝配的方式構造 bean 對象 return autowireConstructor(beanName, mbd, null, null); } else { //經過默認的無參構造方法進行 //todo 經過默認的無參構造方法 return instantiateBean(beanName, mbd); } } Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // todo 使用特定的構造方法完成自動裝配 return autowireConstructor(beanName, mbd, ctors, args); } // No special handling: simply use no-arg constructor. //todo 使用默認的無參構造方法進行初始化 return instantiateBean(beanName, mbd); }
咱們主要關注上面代碼的determineConstructorsFromBeanPostProcessors(beanClass, beanName)
這個方法的目的就是推測實例化須要的構造方法, 爲何須要先推測構造方法呢? 由於Spring實例化對象時,須要使用特定的構造方法才能反射出對象,這時若是程序員指定了帶參數的構造方法,spring就會使用這個構造方法實例化對象,若是程序員提供了一個不帶任何參數的默認構造方法,Spring會忽略它,按本身的邏輯使用默認的無參構造
因此上面的if-else分支目的很明確,先是嘗試獲取所有的構造方法,而後看看有沒有解析出來構造方法, 解析出來的話,就使用第一種邏輯,按照 特殊的構造方法模式進行處理,有解析出來,就使用默認的構造方法
咱們進一步跟進這個determineConstructorsFromBeanPostProcessors(beanClass, beanName)
方法,能夠發現方法裏面又是一波後置處理器的回調工做,此次選出的後置處理器的類型是SmartInstantiationAwareBeanPostProcessor
,見名知意,這種處理器能夠感知到心儀的構造方法,它的主要實現邏輯就是,查看這個將被實例化的對象中有沒有添加了@Lookup
註解的方法,有的話爲這種方法生成代理,循環遍歷全部的構造方法,看看這些構造方法上存在不存在@Value
或者@Autowired
註解,由於這些註解中存在required=true,只要存在這種註解,Spring就將他當成候選的構造方法,可是若是存在多個的話,Spring也不知道到底用哪個,可是在這裏Spring會將全部符合條件的都選出來,可是通常狀況下,均可以正確的選出合適的構造
選擇出合適構造方法以後,就根據不一樣的構造方法,選擇使用不一樣的方式去實例化對象, 都有什麼方式呢? 兩種方式
方式1:
這是比較複雜的方式,此時Spring須要在這個方法內存比較好幾個候選的構造方法,計算它們的差別值,最終值最小的構造函數就是將要用來實例化對象的構造函數,固然極可能是選不出合適的構造函數的,因而Spring沒有當即拋出異常,而是將異常添加進bean工廠的suppressedExceptions這個set集合中
若是成功的選擇出來一個構造函數,就會使用jdk原生的反射機制,實例化一個對象
autowireConstructor(beanName, mbd, ctors, args);
方式2:
直接使用JDK原生的反射機制,實例化一個對象
instantiateBean(beanName, mbd);
小結:
代碼看到這裏,方纔說的有才華的那個類AbstactAutowiredCapatableBeanFactory
中的doCreateBean()
方法的instanceWrapper = createBeanInstance(beanName, mbd, args);
也就看完了, 到這裏也就知道了,Spring會先把全部知足條件的bean所有實例化存放起來,這裏的對象是百分百原生java對象,不摻水不含糖
接着往下看,我把代碼重寫貼出來, 下面還有五件大事,這四件大事說完了,本文就結束了
第一: 是applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
回調後置處理器,進行有關注解的緩存操做
第二: 是getEarlyBeanReference(beanName, mbd, bean)
獲取一個提前暴露的beanDefinition對象,用於解決循環依賴問題
第三: 將剛纔建立原生java對象存放一個叫singletonFactories
的map中,這也是爲了解決循環依賴而設計的數據結構,舉個例子: 如今準備建立A實例, 而後將A實例添加到這個singletonFactories
中, 繼續運行發現A實例依賴B實例,因而在建立B實例,接着又發現B實例依賴A實例,因而從singletonFactories
取出A實例完成裝配,再將B返回給A,完成A的裝配
synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // todo 重點再來看這個 addSingleFactory // todo 將原始對象new出來以後放到了 這個方法中的map中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; // todo 到目前爲止仍是原生對象 try { //todo 用來填充屬性 //設置屬性,很是重要 populateBean(beanName, mbd, instanceWrapper); // todo 通過AOP處理,原生對象轉換成了代理對象,跟進去 //執行後置處理器,aop就是在這裏完成的處理 exposedObject = initializeBean(beanName, exposedObject, mbd); }
接着看populateBean(beanName, mbd, instanceWrapper);
方法,這個方法很重要,就是在這個方法中進行bean屬性的裝配工做,啥意思呢? 好比如今裝配A實例,結果發現A實例中存在一個屬性是B實例,這是就得完成自動裝配的工做,源碼以下:
若是仔細看,就會發現兩個事:
第一: 若是不出意外,就會出現兩次後置處理器的回調,第一後置處理器的回調是判斷當前的bean中是否存在須要裝配的屬性,而第二波後置處理器的回調就是實打實的去完成裝配的動做
第二: 下面的第一個處理器其實就是spring啓動過程當中第一個回調的處理器,只不過調用了這個處理器的不一樣的方法postProcessAfterInstantiation()
,默認返回ture表示按照正常的流程裝配對象的屬性,返回false,表示不會繼續裝配對象中的任何屬性
而咱們則繼續關注下面方法中的第二個後置處理器的,看看Spring是如何完成屬性的自動裝配的,關於這部分的跟蹤,我寫在下面代碼的後面
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { //todo 進行了強轉, InstantiationAwareBeanPostProcessor這個接口前面說過 // todo 只要是經過這個接口返回出來的bean Spring不在管這個bean,不給他裝配任何屬性 //todo 當前這裏沒有用它這個變態的特性 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // todo postProcessAfterInstantiation()默認是返回true, 加上! 表示false if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } // todo Spring內部能夠對BeanDefinition進行設置值, 參照自定義的 BeanFactory中獲取到BeanDefinition.getPropertyValue().addXXX(); PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // todo 判斷當前bean的解析模型是 byName 仍是 byType // todo 再次驗證了::: 當程序員直接使用@Autowired註解時, 既不是ByName 也不是ByType, 而是No if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { if (pvs == null) { pvs = mbd.getPropertyValues(); } //todo 獲取出對象的全部set get方法,如今是有一個 getClass()方法,由於繼承了Object, 沒什麼其餘卵用 PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
好,繼續跟進pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(),
,看看spring如何完成屬性的自動裝配,固然,仍是那句話,若是咱們直接跟進去這個方法進入的是InstantiationAwareBeanPostProcessor
抽象接口抽象方法,而咱們關注的是它的實現類AutowiredAnnotationBeanDefinitionPostProcessor
的實現,打上斷點依次跟進
@Override public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { // todo 跟進來, 目的是 爲 beanName 填充上屬性 bean metadata.inject(bean, beanName, pvs);
跟進
metadata.inject(bean, beanName, pvs);
源碼以下:
能夠這樣理解,在下面的方法中遍歷當前對象中全部可能須要依賴注入的屬性字段
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { // todo 這裏的 InjectedElement 表示單個的須要注入的元素對象 Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { if (logger.isDebugEnabled()) { logger.debug("Processing injected element of bean '" + beanName + "': " + element); } //todo 跟進 AutowiredAnnotationBeanPostProcessor 對這個方法的實現, 在600多行處 element.inject(target, beanName, pvs); } } }
跟進這個inject()
我是手動刪除了這個方法中其餘的不少判斷,僅僅保存下來了下面咱們關注的邏輯,邏輯很清楚,上面的代碼中不是在遍歷全部須要自動裝配的field嗎?若是找到了的話,就得完成自動裝配,自動裝配什麼呢? 其實就是自動裝配上當前對象依賴的其餘的對象而已,由於咱們使用的後置處理器是AutowireAnnotationBeanPostProcessor
經過下面的代碼就能得出結論就是@Autowired
默認狀況下是經過反射實現的自動裝配
// todo 來到這裏 @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } } }
咱們一路往下跟進resolveDependency()
咱們關注這個方法以下代碼:
if (instanceCandidate instanceof Class) {// todo !!!!!當運行到這行代碼時, myService尚未被實例化(singletonObjects中沒有) 執行完這一個行代碼以後, IndexDao1完成了對myService的裝配 instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); }
跟進這個resolveCandidate()
源碼以下:
很直接發現,出現的遞歸的現象,這其實解析清楚了Spring是如何完成屬性注入的,就是隻不過前先後後不少接口不少類,會擾亂這個閱讀的過程
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) throws BeansException { // todo 從bean工廠的獲取, beanName = myService requiredType = com.changwu...OrderService2 , 跟進去這個方法, 他調用了AbstractBeanFactory中的getBean(){ doGetBean();} return beanFactory.getBean(beanName); }
完成裝配後,其實如今的對象依然是原生的java對象 回到AbstractAutowireCapableBeanFactory
中的initializeBean()
方法,源碼以下, 看了下面的代碼就是知道了爲何applyBeanPostProcessorsBeforeInitialization
和init()
和applyBeanPostProcessorsAfterInitialization()
之間的調用順序了
還有最後一個祕密須要揭開: Spring的AOP不是產生了代理對象? 那何時完成的代理呢?畢竟從我開始寫這篇文章到最後都沒有看到,其實AOP的實現就在下面的代碼中
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //todo 執行所有的後置處理器的 Before方法 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // todo 執行全部的init方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { // todo 執行全部的後置處理器的 after方法 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
咱們在前面知道當遇到這個AbstractAutoProxyCreator
時,回調它的before()
方法時,僅僅是標記哪些對象須要進行加強哪些對象不需加強,而沒有當即生成代理對象
如今咱們關注這行代碼wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
,生成代理對象的邏輯就在這裏面
@Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { // todo 進入 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
看這個方法wrapIfNecessary(bean, beanName, cacheKey);
最終會進入這個實現中
你們能夠看到Spring爲bean生成了代理對象,默認會先檢查被代理的對象有沒有實現接口,若是實現了接口,就是用jdk動態代理,不然就看看有沒有cglib的相關依賴,若是存在的相關依賴而沒有實現接口,就會使用cglib的代理模式
另外,補充經過編碼的方式控制 下面的if條件
config.isOptimize()
-> 能夠經過XMl配置, 默認falseconfig.isProxyTargetClass()
-> @EnableAspectjAutoPeoxy(true)
默認也是false@SuppressWarnings("serial") public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { //todo 目標對象是一個接口, 一樣是使用jdk的動態代理 return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { // todo 因此默認使用的是 jdk的動態代理 return new JdkDynamicAopProxy(config); } }