spring-bean 組件是 Spring IoC 的核心,咱們可使用它的 beanFactory 來獲取所需的對象,對象的實例化、屬性裝配和初始化等均可以交給 spring 來管理。 本文將從DefaultListableBeanFactory.getBean(Class)
方法開始分析獲取 bean 的過程,主要內容以下,因爲篇幅較長,能夠根據須要選擇閱讀:html
spring-bean 的源碼比較多,有些不影響總體分析思路的代碼會被省略掉(代碼中會註明),另外,想要分析全部的代碼可能不大現實,因此,針對部份內容,我會點到爲止,例如,本文只分析單例 bean 而不分析多例 bean。java
上篇博客Spring源碼系列(一)--詳細介紹bean組件介紹了 bean 組件的一些重要理論概念,並經過例子演示如何使用 bean 組件。這裏回顧下,這幾個概念很是重要,是 bean 組件的理論基礎:git
從客戶端來看,一個完整的 beanFactory 工廠包含如下基本功能:github
AliasRegistry
接口。SingletonBeanRegistry
接口。BeanDefinition
對象。對應下圖的BeanDefinitionRegistry
接口。BeanFactory
接口。在 spring-bean 組件中,DefaultListableBeanFactory
就是一個完整的 beanFactory 工廠,也能夠說是一個 IoC 容器。spring
BeanFactory
還有幾個擴展接口,用的比較多的多是ConfigurableBeanFactory
和AutowireCapableBeanFactory
:數組
HierarchicalBeanFactory
用於提供父子工廠的支持。例如,當前 beanFactory 找不到 bean 時,會嘗試從 parent beanFactory 中獲取。ConfigurableBeanFactory
用於提供配置 beanFactory 的支持。例如,註冊BeanPostProcessor
、註冊 TypeConverter
、註冊OrderComparator
等。ListableBeanFactory
用於提供批量獲取 bean 的支持(不包含父工廠的 bean)。例如,咱們能夠根據類型獲取 beanName-bean 的 map。AutowireCapableBeanFactory
用於提供實例化、屬性裝配、初始化等一系列管理 bean 生命週期的支持。 例如,該接口包含了 createBean、autowireBean、initializeBean、destroyBean 等方法。當咱們註冊 bean 時,根據註冊方式的不一樣,bean 的註冊信息會被放入兩個不一樣的地方。緩存
class DefaultSingletonBeanRegistry { // beanName=singletonObject鍵值對 // 除了registerSingleton的會放在這裏,registerBeanDefinition生成的單例bean實例也會放在這裏 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); } class DefaultListableBeanFactory { // beanName=beanDefination鍵值對 private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); }
接下來開始分析源碼,註冊 bean 比較簡單,這裏就不看了,咱們直接看 getBean(Class) 的代碼。多線程
進入到 DefaultListableBeanFactory.getBean(Class)
方法,並逐漸展開。在DefaultListableBeanFactory.resolveBean(ResolvableType, Object[], boolean)
方法中,若是當前 beanFactory 中獲取不到這個 bean,將嘗試從 parent beanFactory 中獲取,這也說明了一點:父子 beanFactory 中容許存在相同 beanName 的 bean,只是獲取時當前 beanFactory 的優先級更高一些。app
public <T> T getBean(Class<T> requiredType) throws BeansException { // 適配入參 // 能夠看到,咱們獲取bean時還能夠指定構造參數 return getBean(requiredType, (Object[]) null); } public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException { Assert.notNull(requiredType, "Required type must not be null"); // 繼續適配入參 // 這裏的第三個參數表示,若是指定類型對應的beanName不惟一時,true爲返回null, false爲拋出異常 Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false); // 若是獲取不到這個bean,拋出異常 if (resolved == null) { throw new NoSuchBeanDefinitionException(requiredType); } return (T) resolved; } private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) { // 這裏的NamedBeanHolder就是簡單的對bean實例封裝了一層,不用太關注 NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull); // 若是獲取獲得bean實例,則返回 if (namedBean != null) { return namedBean.getBeanInstance(); } // 若是沒有,嘗試從parent beanFactory中獲取 // 這部分代碼省略······ return null; }
經過 beanType 來獲取 bean,可能會存在一個類型關聯了多個 beanName 的狀況,使用例子中咱們說過,能夠經過指定 beanDefination 的 isPrimary = true 或者註冊比較器的方式來解決。接下來咱們看下具體的處理過程。post
進入到DefaultListableBeanFactory.resolveNamedBean(ResolvableType, Object[], boolean)
方法。若是指定類型匹配到了多個 beanName,會進行如下處理:
registerSingleton
註冊的 beanName,或者經過registerBeanDefinition
註冊且 autowireCandidate = true
的 beanName,則僅保留它們,並剔除其餘的 beanName;registerBeanDefinition
且isPrimary = true
的(存在多個會報錯),存在的話將它做爲匹配到的惟一 beanName;OrderComparator
來肯定優先值最小的做爲惟一 beanName,注意,經過registerSingleton
註冊的和經過registerBeanDefinition
註冊的,比較的對象是不同的;NoUniqueBeanDefinitionException
異常。private <T> NamedBeanHolder<T> resolveNamedBean( ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException { Assert.notNull(requiredType, "Required type must not be null"); // 獲取指定類型的全部beanName,可能匹配到多個 String[] candidateNames = getBeanNamesForType(requiredType); // 若是指定類型匹配到了多個beanName,進行如下操做: // 若是存在經過registerSingleton註冊的beanName,或者經過registerBeanDefinition註冊且 autowireCandidate = true的beanName,則僅保留它們,並剔除其餘的beanName; if (candidateNames.length > 1) { List<String> autowireCandidates = new ArrayList<>(candidateNames.length); for (String beanName : candidateNames) { if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) { autowireCandidates.add(beanName); } } if (!autowireCandidates.isEmpty()) { candidateNames = StringUtils.toStringArray(autowireCandidates); } } // 若是隻剩下一個beanName,那就根據beanName和beanType獲取bean if (candidateNames.length == 1) { String beanName = candidateNames[0]; return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args)); } // 若是存在多個,則還要進一步處理 else if (candidateNames.length > 1) { Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length); // 遍歷候選的beanName for (String beanName : candidateNames) { // 若是該beanName是經過registerSingleton註冊的,且傳入構造參數爲空 // 則獲取該bean實例,並放入candidates if (containsSingleton(beanName) && args == null) { Object beanInstance = getBean(beanName); candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance)); } else { // 其餘狀況下,則獲取該beanName對應的類型,並放入candidates // 注意,這裏的類型不必定是咱們入參指定的類型,例如,若是我指定的是UserServiceFactoryBean.class,這裏返回的倒是UserService.class candidates.put(beanName, getType(beanName)); } } // 若是裏面存在惟一一個經過registerBeanDefinition註冊的且isPrimary=true(存在多個會報錯),則將它做爲匹配到的惟一beanName String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass()); // 若是仍是肯定不了,則經過咱們註冊的OrderComparator來判斷candidates中value的優先數,挑選優先數最小的value對應的key做爲惟一的beanName if (candidateName == null) { candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass()); } if (candidateName != null) { Object beanInstance = candidates.get(candidateName); // 若是candidates中的value自己就是一個bean實例,那麼直接返回就行了 // 若是不是,則根據beanName和beanType獲取bean if (beanInstance == null || beanInstance instanceof Class) { beanInstance = getBean(candidateName, requiredType.toClass(), args); } return new NamedBeanHolder<>(candidateName, (T) beanInstance); } // 若是仍是肯定不了惟一beanName,且設置了nonUniqueAsNull=false(默認爲false),則會拋錯 if (!nonUniqueAsNull) { throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet()); } } return null; }
進入AbstractBeanFactory.getBean(String, Class<T>, Object...)
。這個方法裏包括四個步驟:
BeanNotOfRequiredTypeException
。public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException { // 適配入參 // 這裏最後一個參數指獲取的bean是否純粹用於類型檢查,若是是的話,beanFactory不會標記這個bean正在生成中,僅對單例bean有用 return doGetBean(name, requiredType, args, false); } @SuppressWarnings("unchecked") protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 轉義咱們傳入的name,這裏包括兩個內容: // 1. 若是是別名,須要轉換爲別名對象的beanName; // 2. 若是是「&」+factoryBeanName,則須要去掉前面的「&」 final String beanName = transformedBeanName(name); Object bean; // 獲取單例 // 注意,這裏獲取到的有多是已經初始化,也有多是還沒初始化,甚至還沒裝配的bean Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 省略日誌部分······ // 獲取bean,由於sharedInstance有多是factoryBean,若是咱們要的是factoryBean對應的bean,則還要getObject bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 若是當前線程已經在生成beanName對應的bean,就會拋錯 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 若是當前beanFactory沒有指定的beanName,則會去parent beanFactory中獲取 // 這部分省略······ // 這裏標記指定bean正在建立中,通常對單例bean纔有意義 if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // 獲取指定beanName對應的RootBeanDefinition對象 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 檢查RootBeanDefinition,目前就是檢查是否對應的類型爲抽象類,是的話拋錯 checkMergedBeanDefinition(mbd, beanName, args); // 若是當前bean須要依賴其餘bean,則會先獲取依賴的bean // 這部分省略······ // 建立單例bean if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { // 進入建立bean或factoryBean return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); // 獲取bean實例 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 建立多例bean else if (mbd.isPrototype()) { Object prototypeInstance = null; try { // 標記當前線程正在建立這個bean beforePrototypeCreation(beanName); // 進入建立bean或factoryBean prototypeInstance = createBean(beanName, mbd, args); } finally { // 去掉當前線程中這個bean正在建立的標記 afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } // 接下來這種通常是自定義Scope的狀況,這裏省略不討論 else { // ······· } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // 若是獲取到的bean實例不是咱們指定的類型 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) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
因爲單例 bean 和多例 bean 的建立差很少,本文只選擇單例的來分析。
進入DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory)
。這個方法包括幾個過程,主要就是處理一些多線程問題:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); // 這裏我不是很理解,爲何使用singletonObjects做爲鎖 // 由於從earlySingletonObjects/singletonFactories中獲取已經實例化但可能還沒裝配或初始化的 bean時,用的鎖也是singletonObjects,這樣的話,提早暴露的機制好像就廢掉了啊???TODO synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { // 若是當前beanFactory的單例正在銷燬,則不容許建立單例 if (this.singletonsCurrentlyInDestruction) { // 省略拋錯······ } // 判斷當前bean是否是已經在建立中,是的話拋出BeanCurrentlyInCreationException // 因爲加了鎖,這種狀況應該是不會發生的 beforeSingletonCreation(beanName); boolean newSingleton = false; // 省略部分代碼······ try { // 這裏的執行的是createBean方法 singletonObject = singletonFactory.getObject(); newSingleton = true; } // 這種狀況我不是很理解,singletonObjects的操做不該該被鎖住了嗎?TODO catch (IllegalStateException ex) { singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } // 若是拋出的是BeanCreationException, catch (BeanCreationException ex) { // 省略部分代碼······ throw ex; } finally { // 省略部分代碼······ // 若是當前bean不處於建立狀態中,會拋出IllegalStateException afterSingletonCreation(beanName); } // 若是建立成功,將bean實例加入singletonObjects,而且刪除掉singletonFactories和earlySingletonObjects中對應的鍵值對 if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
以上方法中,若是獲取不到已生成的單例 bean,則會開始建立 bean。
進入AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])
。這個方法包括如下過程:
RootBeanDefinition
;InstantiationAwareBeanPostProcessor
的postProcessBeforeInstantiation
方法,若是返回了非空對象,則將其返回。也就是說咱們能夠在該方法中自定義完成 bean 的實例化、裝配和初始化。protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { RootBeanDefinition mbdToUse = mbd; // 解析當前RootBeanDefinition對應生成的bean類型,並進行再次包裝 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // 省略部分代碼······ try { // 執行咱們註冊的InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法。也就是說咱們能夠在該方法中自定義完成 bean 的實例化、裝配和初始化。 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); // 若是該方法返回bean,那就直接返回 if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { // 建立bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
進入AbstractAutowireCapableBeanFactory.doCreateBean(String, RootBeanDefinition, Object[])
。這個方法主要包含如下過程:
MergedBeanDefinitionPostProcessor
的postProcessMergedBeanDefinition
方法;protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; // 實例化 // 若是是單例,嘗試從factoryBeanInstanceCache中獲取 if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } // 實例化bean if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 執行咱們註冊的MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法 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; } } // 單例的能夠將還沒裝配和初始化的bean先暴露出去,即放在singletonFactories中 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; try { // 屬性裝配 populateBean(beanName, mbd, instanceWrapper); // 初始化 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } // 省略部分代碼······ // 將生成的bean或factoryBean放入disposableBeans中 try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
接下來將展開 bean 的實例化、屬性裝配和初始化。其中,實例化和屬性裝配的代碼比較複雜,咱們重點分析,至於初始化部分,則留給讀者自行閱讀。
進入AbstractAutowireCapableBeanFactory.createBeanInstance(String, RootBeanDefinition, Object[])
。這個方法主要過程以下:
SmartInstantiationAwareBeanPostProcessor
的determineCandidateConstructors
獲取構造對象數組;protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { // 解析bean類型 Class<?> beanClass = resolveBeanClass(mbd, beanName); // 若是bean類型不是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()); } // 經過RootBeanDefinition中定義的Supplier來獲取實例化bean Supplier<?> instanceSupplier = mbd.getInstanceSupplier(); if (instanceSupplier != null) { return obtainFromSupplier(instanceSupplier, beanName); } // 經過RootBeanDefinition中定義FactoryMethod來實例化bean if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // 若是構造參數爲空,則能夠複用已經解析好的構造對象(若是有的話) boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { return autowireConstructor(beanName, mbd, null, null); } else { return instantiateBean(beanName, mbd); } } // 執行咱們註冊的SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors獲取Constructor對象數組(若是有的話) Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); // 若是獲得的數組不是空,或者beanDefination的裝配模式爲構造注入,或者beanDefination包含構造參數,或者咱們傳入的構造參數非空,則進入實例化bean或factoryBean if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // 省略部分代碼······ // 使用無參構造實例化bean或factoryBean return instantiateBean(beanName, mbd); }
實例化的方法包括有參構造實例化和無參構造實例化兩種,本文只討論有參構造實例化的狀況。
在繼續分析以前,有必要了解下ConstructorArgumentValues
和ArgumentsHolder
這兩個類。
首先,ConstructorArgumentValues
用於定義構造方法的參數列表的值。spring 中,ConstructorArgumentValues
通常被定義在 BeanDefinition
對象中,它影響着 bean 的實例化,是 bean 實例化時選擇構造對象的依據。
public class ConstructorArgumentValues { // 索引+參數值 // 例如,對應new User(int age, String name, String address)的構造方法,能夠包含元素:0=new ValueHolder(18),2=new ValueHolder("北京") private final Map<Integer, ValueHolder> indexedArgumentValues = new LinkedHashMap<>(); // 通用參數值 // 例如,對應new User(int age, String name, String address)的構造方法,若是indexedArgumentValues中不包含name的值,則能夠在genericArgumentValues中查找,咱們只須要添加元素:new ValueHolder("zzs001", String.class) private final List<ValueHolder> genericArgumentValues = new ArrayList<>(); // 內部類,表明一個參數的值 public static class ValueHolder implements BeanMetadataElement { @Nullable private Object value; @Nullable private String type; @Nullable private String name; @Nullable private Object source; private boolean converted = false; }
ArgumentsHolder
是ConstructorResolver
的內部類,和ConstructorArgumentValues
同樣,它也是用來定義構造方法的參數列表的值,區別在於,ConstructorArgumentValues
的值是「未解析的」,而ArgumentsHolder
包含了「未解析」(preparedArguments)、「解析未完成」(rawArguments)和"解析完成"(arguments)三種值。
爲何會這樣呢?由於ConstructorArgumentValues
中的參數值的類型不必定和構造方法中的匹配,包括兩種狀況:
TypeConverter
轉換的類型。例如,在new User(int age, String name, Address address)
的構造方法中,我能夠在ConstructorArgumentValues
添加2=new AddressVO()
,這個時候只要 spring 能找到合適的轉換器就能轉換,這個轉換過程爲:「解析未完成」(rawArguments) --》 "解析完成"(arguments)。new User(int age, String name, Address address)
的構造方法中,我能夠在ConstructorArgumentValues
添加2=new RootBeanDefinition(Address.class)
,這個轉換過程爲:「未解析」(preparedArguments) --》「解析未完成」(rawArguments)。private static class ArgumentsHolder { public final Object[] rawArguments; public final Object[] arguments; public final Object[] preparedArguments; public boolean resolveNecessary = false; }
理解完這兩個類以後,咱們繼續分析實例化的源碼。
進入到AbstractAutowireCapableBeanFactory.autowireConstructor(String, RootBeanDefinition, Constructor<?>[], Object[])
方法。這裏建立了一個ConstructorResolver
對象並直接調用它的 autowireConstructor 方法。
protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) { return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs); }
進入ConstructorResolver.autowireConstructor(String, RootBeanDefinition, Constructor<?>[], Object[])
。這個方法代碼比較多,爲了更好地理解,能夠分紅兩種場景來看:
BeanDefinition
對象中指定ConstructorArgumentValues
。這種場景的參數值須要通過兩步轉換,該場景要求對應的構造對象的參數數量不小於指定的數量。public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) { BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); // 定義最終用於實例化對象的構造器 Constructor<?> constructorToUse = null; // 定義存放(「未解析」、「解析未完成」、「解析完成」)構造參數的對象 ArgumentsHolder argsHolderToUse = null; // 定義最終用於實例化對象的構造參數 Object[] argsToUse = null; // 入參顯式聲明瞭構造參數(場景一),則不須要解析參數列表值,但需解析構造對象 if (explicitArgs != null) { argsToUse = explicitArgs; } else { Object[] argsToResolve = null; // BeanDefinition對象中指定ConstructorArgumentValues(場景二),若是參數列表值或構造對象已經解析,則不須要再解析 synchronized (mbd.constructorArgumentLock) { constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; if (constructorToUse != null && mbd.constructorArgumentsResolved) { // Found a cached constructor... argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments; } } } if (argsToResolve != null) { argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true); } } // 進入解析參數列表值和構造對象 if (constructorToUse == null || argsToUse == null) { // 若是入參裏沒有顯式指定構造對象的數組,使用反射方式獲取 Constructor<?>[] candidates = chosenCtors; if (candidates == null) { Class<?> beanClass = mbd.getBeanClass(); try { // BeanDefinition中能夠定義是否包括非public的方法 candidates = (mbd.isNonPublicAccessAllowed() ? beanClass.getDeclaredConstructors() : beanClass.getConstructors()); } catch (Throwable ex) { // 省略代碼······ } } // 若是數組中只有一個無參構造,且入參和BeanDefinition中都未指定參數列表值,則標記該BeanDefinition對象的構造參數已解析,並實例化bean if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) { // 省略代碼······ } // 判斷是否須要解析構造 boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR); // 這裏存放「解析未完成」的參數列表值 ConstructorArgumentValues resolvedValues = null; // 獲取要求構造參數的最小數量 int minNrOfArgs; // 入參顯式聲明瞭構造參數(場景一),minNrOfArgs即爲指定數組的長度 if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { // BeanDefinition對象中指定ConstructorArgumentValues(場景二),則須要計算minNrOfArgs,並進行「未解析」 --> 「解析未完成」的轉換 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); resolvedValues = new ConstructorArgumentValues(); minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } // 根據參數數量從小到大排列 AutowireUtils.sortConstructors(candidates); int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; LinkedList<UnsatisfiedDependencyException> causes = null; // 遍歷候選的構造對象 for (Constructor<?> candidate : candidates) { // 獲取當前構造對象的參數數量 int parameterCount = candidate.getParameterCount(); // 若是上一個循環已經找到匹配的構造對象,則跳出循環1 if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) { break; } // 若是當前構造對象的參數數量小於minNrOfArgs,則遍歷下一個 // 注意,入參裏顯式指定構造參數(場景一)要求對應的構造對象的參數數量必須和指定的同樣。BeanDefinition對象中指定ConstructorArgumentValues(場景二)要求對應的構造對象的參數數量不小於指定的數量 if (parameterCount < minNrOfArgs) { continue; } ArgumentsHolder argsHolder; // 獲取當前構造對象的參數類型數組 Class<?>[] paramTypes = candidate.getParameterTypes(); // BeanDefinition對象中指定ConstructorArgumentValues(場景二)的狀況 if (resolvedValues != null) { // 進行「解析未完成」->「解析完成」的轉換 try { // 這裏是爲了處理JDK6的ConstructorProperties註解,其餘狀況都會返回null。 String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount); if (paramNames == null) { ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { // 獲取當前構造對象的參數名數組 paramNames = pnd.getParameterNames(candidate); } } // 建立ArgumentsHolder對象 argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1); } catch (UnsatisfiedDependencyException ex) { // 省略代碼······ continue; } } // 入參裏顯式指定構造參數(場景一)的狀況 else { // 若是當前構造參數的數量小於指定參數的數量,則繼續循環 if (parameterCount != explicitArgs.length) { continue; } // 建立ArgumentsHolder對象,由於不須要解析參數,因此,這種狀況raw、prepared、resolved都是同樣的 argsHolder = new ArgumentsHolder(explicitArgs); } // 計算指定參數和當前構造的參數類型的差別值 int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); // 差別值小於閾值 if (typeDiffWeight < minTypeDiffWeight) { // 獲得匹配的構造對象和構造參數 constructorToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousConstructors = null; } // 差別值大於閾值,這種不考慮 else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) { // 省略代碼······ } } // 若是找不到合適的構造對象,則會拋錯 if (constructorToUse == null) { // 省略代碼······ } else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) { // 省略代碼······ } // BeanDefinition對象中指定ConstructorArgumentValues(場景二),爲了複用解析好的構造和參數列表,須要標記當前BeanDefinition的構造參數已解析 if (explicitArgs == null && argsHolderToUse != null) { argsHolderToUse.storeCache(mbd, constructorToUse); } } Assert.state(argsToUse != null, "Unresolved constructor arguments"); // 接下來就是使用構造對象和參數來實例化對象,就不往下看了。 bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse)); return bw; }
實例化部分比較難,主要還得先理解一些抽象概念,例如:兩個場景、參數的轉換等。
進入AbstractAutowireCapableBeanFactory.populateBean(String, RootBeanDefinition, BeanWrapper)
。這個方法包括如下過程:
InstantiationAwareBeanPostProcessor
的postProcessAfterInstantiation
方法,若是返回了 false,則不進行屬性裝配,直接返回;PropertyValues
對象,根據 beanDefinition 設置的注入類型,填充PropertyValues
對象;InstantiationAwareBeanPostProcessor
的postProcessProperties
方法,能夠對PropertyValues
對象進行修改;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 { return; } } // 執行咱們註冊的InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法,若是返回了false,則不進行屬性裝配,直接返回 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } // 獲取BeanDefinition對象中的PropertyValues,包含了name=value的PropertyValue對象的列表 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 根據咱們設置的注入方式,填充 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 按名字裝配 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 按類型裝配 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } // beanFactory中是否註冊了InstantiationAwareBeanPostProcessors boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // BeanDefinition對象中是否設置了依賴檢查 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { // 若是爲空,再次從BeanDefinition對象中獲取,TODO? pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 執行咱們註冊的InstantiationAwareBeanPostProcessor的postProcessProperties方法,能夠對PropertyValues對象進行修改 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); // 省略部分代碼······ pvs = pvsToUse; } } } // 若是BeanDefinition對象中設置了依賴檢查,則須要檢查依賴設置 if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { // 執行屬性裝配 applyPropertyValues(beanName, mbd, bw, pvs); } }
這個方法中主要涉及autowireByName
、autowireByType
和applyPropertyValues
三個方法,前兩個暫時不展開,只講最後一個方法。
在分析applyPropertyValues
方法以前,咱們須要知道一下幾個知識點。這裏以User
這個類來展開例子。
public class User { private String name; private int age; private Address address; private List<String> hobbies; } class Address { private String region; private String desc; }
當咱們給 beanDefinition設置屬性值時,通常都會這樣採用這樣的賦值,這裏成爲「普通形式」。
rootBeanDefinition.getPropertyValues().add("name", "zzs001"); rootBeanDefinition.getPropertyValues().add("age", 18); rootBeanDefinition.getPropertyValues().add("address", new Address("", "")); rootBeanDefinition.getPropertyValues().add("hobbies", new ArrayList());
針對類型爲 object、list、array、map 等成員屬性,spring 還支持其餘的賦值方式,以下,分別成爲「嵌套對象形式」和「索引形式」:
// 嵌套對象形式 rootBeanDefinition.getPropertyValues().add("address.region", ""); rootBeanDefinition.getPropertyValues().add("address.desc", ""); // 索引形式 rootBeanDefinition.getPropertyValues().add("hobbies[0]", "");
正是因爲 propertyName 引入了多種的形式,因此,本來簡單的賦值行爲被搞得很是複雜。例如,嵌套對象形式還能夠是這樣:foo.user.address.region
,幾乎能夠一直嵌套下去。
propertyAccessor 對象通常綁定了一個實例對象,經過PropertyAccessor
接口的方法能夠對對象的屬性進行存取操做。屬性裝配中最終對成員屬性賦值就是調用它的setPropertyValue
方法。AbstractNestablePropertyAccessor
中維護了一個 map,key 爲當前綁定對象的屬性名(不包含嵌套和索引),value 就是對於的PropertyAccessor
對象。
public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyAccessor { private Map<String, AbstractNestablePropertyAccessor> nestedPropertyAccessors; }
在上面的例子中,
rootBeanDefinition.getPropertyValues().add("name", "zzs001"); rootBeanDefinition.getPropertyValues().add("age", 18);
這種形式共用一個綁定了User
類型實例的PropertyAccessor
對象。
// 嵌套對象形式 rootBeanDefinition.getPropertyValues().add("address.region", ""); rootBeanDefinition.getPropertyValues().add("address.desc", "");
這種形式共用一個綁定了Address
類型實例的PropertyAccessor
對象,該對象和"address"這個名字關聯起來維護在 nestedPropertyAccessors 中。
// 索引形式 rootBeanDefinition.getPropertyValues().add("hobbies[0]", "");
這種形式也是一個綁定了User
類型實例的PropertyAccessor
對象,該對象和"hobbies"這個名字關聯起來維護在 nestedPropertyAccessors 中。
PropertyTokenHolder
是AbstractNestablePropertyAccessor
的內部類,它更多的是針對「索引形式」的 propertyName。例如,"hobbies[0]"對於的PropertyTokenHolder
中,actualName = hobbies,canonicalName = [0],keys = {0}。
protected static class PropertyTokenHolder { public PropertyTokenHolder(String name) { this.actualName = name; this.canonicalName = name; } public String actualName; public String canonicalName; @Nullable public String[] keys; }
接下來繼續分析屬性裝配的代碼。
進入AbstractAutowireCapableBeanFactory.applyPropertyValues(String, BeanDefinition, BeanWrapper, PropertyValues)
方法。和構造參數同樣,設置成員屬性的參數也須要通過「兩次轉換」,這裏就不詳細講解。這個方法主要包括如下過程:
BeanDefinition
、BeanDefinitionHolder
等的對象,則設置PropertyValues
對象已經轉換完成,下次調用這個方法不用再進行轉換;protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { // 若是沒有須要注入的屬性,直接返回 if (pvs.isEmpty()) { return; } // 省略部分代碼······ MutablePropertyValues mpvs = null; // 獲取屬性對象列表 List<PropertyValue> original; if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; // 若是全部屬性對象已經完成「兩次轉換」,則直接裝配屬性 if (mpvs.isConverted()) { try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { original = Arrays.asList(pvs.getPropertyValues()); } // 獲取咱們註冊的類型轉換器 TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } // 建立第一次轉換所用的解析器 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // 定義一個列表,用於存放完成「兩次轉換」的屬性對象 // 這注意,這裏並無進行所謂的複製,不要被命名迷惑了 List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; // 遍歷屬性對象 for (PropertyValue pv : original) { // 當前屬性對象已經完成「兩次轉換」,直接添加到列表 if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); // 省略部分代碼······ // 第一次轉換 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; // 若是當前屬性爲可寫屬性,且屬性名不是相似於foo.bar或addresses[0]的形式,則須要進行第二次轉換 boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // 若是轉換後的屬性對象和初始對象同樣,通常指的是普通對象,而不是BeanDefinition、BeanDefinitionHolder等 if (resolvedValue == originalValue) { // 若是須要第二次轉換,則設置複用的目標對象 if (convertible) { pv.setConvertedValue(convertedValue); } // 將原屬性對象添加到列表 deepCopy.add(pv); } // 這種狀況不考慮 else if (convertible && originalValue instanceof TypedStringValue && !((TypedStringValue) originalValue).isDynamic() && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); } // 其餘狀況 else { // 標記每次都須要解析 resolveNecessary = true; // 將原屬性對象添加到列表 deepCopy.add(new PropertyValue(pv, convertedValue)); } } } // 若是不包含BeanDefinition、BeanDefinitionHolder等對象,則設置PropertyValues爲已轉換,這樣下次調用這個方法,就不須要進行任何的轉換了 if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // 屬性裝配 try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
進入AbstractPropertyAccessor.setPropertyValues(PropertyValues)
方法。這裏遍歷屬性對象列表,逐個進賦值操做。
public void setPropertyValues(PropertyValues pvs) throws BeansException { // 入參適配 // 後面兩個參數分別表明:是否忽略NotWritablePropertyException異常、是否忽略NullValueInNestedPathException異常 setPropertyValues(pvs, false, false); } public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException { // 獲取屬性對象列表 List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ? ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues())); for (PropertyValue pv : propertyValues) { // 省略try-catch的代碼和其餘異常相關的代碼······ setPropertyValue(pv); } }
進入AbstractNestablePropertyAccessor.setPropertyValue(PropertyValue)
。這個方法包括如下過程:
PropertyAccessor
對象,這裏將解析「嵌套對象形式」的 propertyName;PropertyTokenHolder
對象,這裏將解析「索引形式」的 propertyName;PropertyAccessor
對象進行賦值操做。public void setPropertyValue(PropertyValue pv) throws BeansException { // 適配入參 setPropertyValue(pv.getName(), pv.getValue()); } public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException { AbstractNestablePropertyAccessor nestedPa; try { // 獲取propertyName對應的PropertyAccessor對象,這裏將解析「嵌套對象形式」的propertyName // 若是緩存裏有的話,將複用 nestedPa = getPropertyAccessorForPropertyPath(propertyName); } catch (NotReadablePropertyException ex) { throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName, "Nested property in path '" + propertyName + "' does not exist", ex); } // 建立PropertyTokenHolder對象,這裏將解析「索引形式」的propertyName PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName)); // 使用PropertyAccessor對象進行賦值操做 nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value)); }
進入AbstractNestablePropertyAccessor.setPropertyValue(PropertyTokenHolder, PropertyValue)
方法。這裏根據 propertyName 是否爲「索引形式」調用不一樣的方法。
protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException { if (tokens.keys != null) { processKeyedProperty(tokens, pv); } else { processLocalProperty(tokens, pv); } }
這裏咱們不看 propertyName 爲「索引形式」的方法,只看processLocalProperty
。
private void processLocalProperty(PropertyTokenHolder tokens, PropertyValue pv) { // 獲取actualName對應的PropertyHandler對象,若是有緩存則複用 PropertyHandler ph = getLocalPropertyHandler(tokens.actualName); if (ph == null || !ph.isWritable()) { // 省略部分代碼······ } Object oldValue = null; try { Object originalValue = pv.getValue(); Object valueToApply = originalValue; if (!Boolean.FALSE.equals(pv.conversionNecessary)) { // 由於咱們的屬性參數都是轉換過的,因此這裏再也不看轉換的代碼 if (pv.isConverted()) { valueToApply = pv.getConvertedValue(); } else { // 省略部分代碼······ } pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue); } // 接下來就是經過反射方式給屬性賦值,後續再展開 ph.setValue(valueToApply); } catch (Exception ex) { // 省略部分代碼······ } }
屬性裝配的代碼分析就點到爲止吧。
以上基本看完 spring-bean 的源碼。針對 getBean 的過程,本文未展開的內容包括:
感興趣的讀者能夠自行分析。另外,以上內容若有錯誤,歡迎指正。
最後,感謝閱讀。
相關源碼請移步: spring-beans
本文爲原創文章,轉載請附上原文出處連接:http://www.javashuo.com/article/p-wyermzob-gw.html