【spring原始碼分析】IOC容器初始化(二)
前言:在【spring原始碼分析】IOC容器初始化(一)中已經分析了匯入bean階段,本篇接著分析bean解析階段。
1.解析bean程式呼叫鏈
同樣,先給出解析bean的程式呼叫鏈:
根據程式呼叫鏈,整理出在解析bean過程中主要涉及的類和相關方法。
2.解析bean原始碼分析
在匯入bean階段,已經分析到XmlBeanDefinitionReader#doLoadBeanDefinitions方法,在解析bean時,首先還是在XmlBeanDefinitionReader中,程式碼如下:
1 public int registerBeanDefinitions(Document doc, Resource resource) throwsBeanDefinitionStoreException { 2 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); 3 int countBefore = getRegistry().getBeanDefinitionCount(); 4 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 5 returngetRegistry().getBeanDefinitionCount() - countBefore; 6 }
分析:
①第2行:首先建立一個BeanDefinitionDocumentReader。
②第3行:取出容器中之前例項化的bean的個數。
③第4行:進入具體解析階段。轉向DefaultBeanDefinitionDocumentReader的registerBeanDefinitions方法:
1 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {2 this.readerContext = readerContext; 3 logger.debug("Loading bean definitions"); 4 Element root = doc.getDocumentElement(); 5 doRegisterBeanDefinitions(root); 6 }
分析:
①第4行:從doc中取出根節點(前面已經將xml檔案轉換成了流,然後再轉換成Document)。
②第5行:進入DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions方法:
1 protected void doRegisterBeanDefinitions(Element root) { 2 // Any nested <beans> elements will cause recursion in this method. In 3 // order to propagate and preserve <beans> default-* attributes correctly, 4 // keep track of the current (parent) delegate, which may be null. Create 5 // the new (child) delegate with a reference to the parent for fallback purposes, 6 // then ultimately reset this.delegate back to its original (parent) reference. 7 // this behavior emulates a stack of delegates without actually necessitating one. 8 BeanDefinitionParserDelegate parent = this.delegate; 9 this.delegate = createDelegate(getReaderContext(), root, parent); 10 11 if (this.delegate.isDefaultNamespace(root)) { 12 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); 13 if (StringUtils.hasText(profileSpec)) { 14 String[] specifiedProfiles = StringUtils.tokenizeToStringArray( 15 profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); 16 if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { 17 if (logger.isInfoEnabled()) { 18 logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + 19 "] not matching: " + getReaderContext().getResource()); 20 } 21 return; 22 } 23 } 24 } 25 26 preProcessXml(root); 27 System.out.println("DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions函式中進行解析" + 28 "主要函式parseBeanDefinitions通過BeanDefinitionParserDelegate進行解析"); 29 parseBeanDefinitions(root, this.delegate); 30 postProcessXml(root); 31 32 this.delegate = parent; 33 }
分析:
①第8、9行:建立BeanDefinitionParserDelegate,通過委託去進行bean的解析。
②重點26-30行:preProcessXml和postProcessXml都是預留給使用者自己實現,以便擴充套件。我們著重關注parseBeanDefinitions(DefaultBeanDefinitionDocumentReader)函式:
1 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { 2 if (delegate.isDefaultNamespace(root)) { 3 NodeList nl = root.getChildNodes(); 4 for (int i = 0; i < nl.getLength(); i++) { 5 Node node = nl.item(i); 6 if (node instanceof Element) { 7 Element ele = (Element) node; 8 if (delegate.isDefaultNamespace(ele)) { 9 System.out.println("對於預設名稱空間的形式走該分支parseDefaultElement(ele, delegate)"); 10 parseDefaultElement(ele, delegate); 11 } 12 else { 13 System.out.println("非預設名稱空間則走該分支delegate.parseCustomElement(ele);"); 14 System.out.println("如果開啟了aop:aspectj-autoproxy,也會走該分支,生成AspectJAutoProxyBeanDefinitionParser解析器"); 15 delegate.parseCustomElement(ele); 16 } 17 } 18 } 19 } 20 else { 21 delegate.parseCustomElement(root); 22 } 23 }
分析:
①第2行:判斷是否屬於預設空間,如果不是則走自定義元素解析分支。
②第10行:如果為元素為預設空間,則轉向DefaultBeanDefinitionDocumentReader的parseDefaultElement方法:
1 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { 2 System.out.println("DefaultBeanDefinitionDocumentReader#parseDefaultElement函式,根據標籤型別進行元素的解析"); 3 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { 4 importBeanDefinitionResource(ele); 5 } 6 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { 7 processAliasRegistration(ele); 8 } 9 else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { 10 processBeanDefinition(ele, delegate); 11 } 12 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { 13 // recurse 14 doRegisterBeanDefinitions(ele); 15 } 16 }
分析:
從該函式中可以非常清晰的看到,走了幾個分支:import、alias、bean和beans。對於不同的分支會進行不同的解析,但大致流程一樣。這裡我們走bean分支,第10行:轉向DefaultBeanDefinitionDocumentReader的processBeanDefinition函式:
1 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { 2 System.out.println("DefaultBeanDefinitionDocumentReader#processBeanDefinition進行解析,返回BeanDefinitionHolder"); 3 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); 4 if (bdHolder != null) { 5 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); 6 try { 7 // Register the final decorated instance. 8 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); 9 } 10 catch (BeanDefinitionStoreException ex) { 11 getReaderContext().error("Failed to register bean definition with name '" + 12 bdHolder.getBeanName() + "'", ele, ex); 13 } 14 // Send registration event. 15 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); 16 } 17 }
分析:
對bean的解析過程在第3行中,通過委託這裡會轉向BeanDefinitionParserDelegate的parseBeanDefinitionElement方法(A段程式碼):
1 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { 2 System.out.println("取出xml的id和name屬性,用於生成beanDefinition"); 3 String id = ele.getAttribute(ID_ATTRIBUTE); 4 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); 5 6 List<String> aliases = new ArrayList<>(); 7 if (StringUtils.hasLength(nameAttr)) { 8 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); 9 aliases.addAll(Arrays.asList(nameArr)); 10 } 11 12 String beanName = id; 13 if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { 14 beanName = aliases.remove(0); 15 if (logger.isDebugEnabled()) { 16 logger.debug("No XML 'id' specified - using '" + beanName + 17 "' as bean name and " + aliases + " as aliases"); 18 } 19 } 20 21 if (containingBean == null) { 22 checkNameUniqueness(beanName, aliases, ele); 23 } 24 25 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); 26 if (beanDefinition != null) { 27 if (!StringUtils.hasText(beanName)) { 28 try { 29 if (containingBean != null) { 30 beanName = BeanDefinitionReaderUtils.generateBeanName( 31 beanDefinition, this.readerContext.getRegistry(), true); 32 } 33 else { 34 beanName = this.readerContext.generateBeanName(beanDefinition); 35 // Register an alias for the plain bean class name, if still possible, 36 // if the generator returned the class name plus a suffix. 37 // This is expected for Spring 1.2/2.0 backwards compatibility. 38 String beanClassName = beanDefinition.getBeanClassName(); 39 if (beanClassName != null && 40 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && 41 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { 42 aliases.add(beanClassName); 43 } 44 } 45 if (logger.isDebugEnabled()) { 46 logger.debug("Neither XML 'id' nor 'name' specified - " + 47 "using generated bean name [" + beanName + "]"); 48 } 49 } 50 catch (Exception ex) { 51 error(ex.getMessage(), ele); 52 return null; 53 } 54 } 55 String[] aliasesArray = StringUtils.toStringArray(aliases); 56 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); 57 } 58 59 return null; 60 }
分析:
①第3、4行:取出配置檔案bean標籤的id和name屬性,id屬性必須有,name可有可無。
②第22行:檢查類名的唯一性。
③第25行:進行元素的解析,BeanDefinitionParserDelegate的parseBeanDefinitionElement方法(B段程式碼):
1 public AbstractBeanDefinition parseBeanDefinitionElement( 2 Element ele, String beanName, @Nullable BeanDefinition containingBean) { 3 4 this.parseState.push(new BeanEntry(beanName)); 5 6 String className = null; 7 if (ele.hasAttribute(CLASS_ATTRIBUTE)) { 8 className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); 9 } 10 String parent = null; 11 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { 12 parent = ele.getAttribute(PARENT_ATTRIBUTE); 13 } 14 15 try { 16 AbstractBeanDefinition bd = createBeanDefinition(className, parent); 17 18 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); 19 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); 20 21 System.out.println("BeanDefinitionParserDelegate#parseBeanDefinitionElement中會對xml中的相關標籤進行解析" + 22 "meta標籤、lookup方法、replaceMethod、建構函式等"); 23 parseMetaElements(ele, bd); 24 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); 25 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); 26 27 parseConstructorArgElements(ele, bd); 28 parsePropertyElements(ele, bd); 29 parseQualifierElements(ele, bd); 30 31 bd.setResource(this.readerContext.getResource()); 32 bd.setSource(extractSource(ele)); 33 34 return bd; 35 } 36 catch (ClassNotFoundException ex) { 37 error("Bean class [" + className + "] not found", ele, ex); 38 } 39 catch (NoClassDefFoundError err) { 40 error("Class that bean class [" + className + "] depends on not found", ele, err); 41 } 42 catch (Throwable ex) { 43 error("Unexpected failure during bean definition parsing", ele, ex); 44 } 45 finally { 46 this.parseState.pop(); 47 } 48 49 return null; 50 }
分析:
①第8行:取出bean標籤中的class屬性,用作反射生成例項物件。
②著重第16行:建立Beandefinition,最終會轉向BeanDefinitionReaderUtils的createBeanDefinition方法:
1 public static AbstractBeanDefinition createBeanDefinition( 2 @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException { 3 4 GenericBeanDefinition bd = new GenericBeanDefinition(); 5 bd.setParentName(parentName); 6 if (className != null) { 7 if (classLoader != null) { 8 bd.setBeanClass(ClassUtils.forName(className, classLoader)); 9 } 10 else { 11 bd.setBeanClassName(className); 12 } 13 } 14 return bd; 15 }
分析:
檢視該方法的原始碼通過註釋可知:該方法會建立一個GenericBeanDefinition,並且如果classLoder已指定,它會立即通過反射例項化物件,如果classLoader未指定,則設定bean的類名(注:這裡的類名為類的全路徑名)。
GenericBeanDefinition建立後轉向B段程式碼的18行(解析bean的預設屬性值):
1 public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, 2 @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) { 3 4 System.out.println("BeanDefinitionParserDelegate#parseBeanDefinitionAttributes對預設屬性進行解析"); 5 if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { 6 error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); 7 } 8 else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { 9 bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); 10 } 11 else if (containingBean != null) { 12 // Take default from containing bean in case of an inner bean definition. 13 bd.setScope(containingBean.getScope()); 14 } 15 16 if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { 17 bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); 18 } 19 20 String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); 21 if (DEFAULT_VALUE.equals(lazyInit)) { 22 lazyInit = this.defaults.getLazyInit(); 23 } 24 bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); 25 26 String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); 27 bd.setAutowireMode(getAutowireMode(autowire)); 28 29 if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { 30 String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); 31 bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); 32 } 33 34 String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); 35 if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) { 36 String candidatePattern = this.defaults.getAutowireCandidates(); 37 if (candidatePattern != null) { 38 String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); 39 bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); 40 } 41 } 42 else { 43 bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); 44 } 45 46 if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { 47 bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); 48 } 49 50 if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { 51 String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); 52 bd.setInitMethodName(initMethodName); 53 } 54 else if (this.defaults.getInitMethod() != null) { 55 bd.setInitMethodName(this.defaults.getInitMethod()); 56 bd.setEnforceInitMethod(false); 57 } 58 59 if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { 60 String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); 61 bd.setDestroyMethodName(destroyMethodName); 62 } 63 else if (this.defaults.getDestroyMethod() != null) { 64 bd.setDestroyMethodName(this.defaults.getDestroyMethod()); 65 bd.setEnforceDestroyMethod(false); 66 } 67 68 if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { 69 bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); 70 } 71 if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { 72 bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); 73 } 74 75 return bd; 76 }
分析:
上面程式碼主要對bean標籤的預設屬性進行解析,主要包括:
1 public static final String ABSTRACT_ATTRIBUTE = "abstract"; 2 3 public static final String SCOPE_ATTRIBUTE = "scope"; 4 5 private static final String SINGLETON_ATTRIBUTE = "singleton"; 6 7 public static final String LAZY_INIT_ATTRIBUTE = "lazy-init"; //懶載入 8 9 public static final String AUTOWIRE_ATTRIBUTE = "autowire"; 10 11 public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate"; 12 13 public static final String PRIMARY_ATTRIBUTE = "primary"; 14 15 public static final String DEPENDS_ON_ATTRIBUTE = "depends-on"; 16 17 public static final String INIT_METHOD_ATTRIBUTE = "init-method"; //初始化方法 18 19 public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method"; //bean銷燬時呼叫方法 20 21 public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method"; 22 23 public static final String FACTORY_BEAN_ATTRIBUTE = "factory-bean";
繼續看B段程式碼的23~32行,分別解析:meta標籤、lookup方法、replaceMethod方法、建構函式等,為例項化物件做準備。在對bean標籤的相關屬性解析完成後,返回到A段程式碼的25行:
1 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); 2 if (beanDefinition != null) { 3 if (!StringUtils.hasText(beanName)) { 4 try { 5 if (containingBean != null) { 6 beanName = BeanDefinitionReaderUtils.generateBeanName( 7 beanDefinition, this.readerContext.getRegistry(), true); 8 } 9 else { 10 beanName = this.readerContext.generateBeanName(beanDefinition); 11 // Register an alias for the plain bean class name, if still possible, 12 // if the generator returned the class name plus a suffix. 13 // This is expected for Spring 1.2/2.0 backwards compatibility. 14 String beanClassName = beanDefinition.getBeanClassName(); 15 if (beanClassName != null && 16 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && 17 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { 18 aliases.add(beanClassName); 19 } 20 } 21 if (logger.isDebugEnabled()) { 22 logger.debug("Neither XML 'id' nor 'name' specified - " + 23 "using generated bean name [" + beanName + "]"); 24 } 25 } 26 catch (Exception ex) { 27 error(ex.getMessage(), ele); 28 return null; 29 } 30 } 31 String[] aliasesArray = StringUtils.toStringArray(aliases); 32 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); 33 } 34 35 return null; 36 }
分析:
這裡會判斷beanName是否為空,如果為空則會通過beanDefinition來生成beanName,如果不為空,則直接轉向32行,生成BeanDefinitionHolder。在生成BeanDefinitionHolder後會返回到DefaultBeanDefinitionDocumentReader的processBeanDefinition函式:
1 if (bdHolder != null) { 2 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); 3 try { 4 // Register the final decorated instance. 5 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); 6 } 7 catch (BeanDefinitionStoreException ex) { 8 getReaderContext().error("Failed to register bean definition with name '" + 9 bdHolder.getBeanName() + "'", ele, ex); 10 } 11 // Send registration event. 12 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); 13 }
分析:
①第2行:對bean的自定義屬性值賦值,這裡會轉向BeanDefinitionParserDelegate的decorateBeanDefinitionIfRequired方法:
1 public BeanDefinitionHolder decorateBeanDefinitionIfRequired( 2 Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) { 3 4 System.out.println("BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired對自定義屬性進行解析"); 5 BeanDefinitionHolder finalDefinition = definitionHolder; 6 7 // Decorate based on custom attributes first. 8 NamedNodeMap attributes = ele.getAttributes(); 9 for (int i = 0; i < attributes.getLength(); i++) { 10 Node node = attributes.item(i); 11 finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); 12 } 13 14 // Decorate based on custom nested elements. 15 NodeList children = ele.getChildNodes(); 16 for (int i = 0; i < children.getLength(); i++) { 17 Node node = children.item(i); 18 if (node.getNodeType() == Node.ELEMENT_NODE) { 19 finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); 20 } 21 } 22 return finalDefinition; 23 }
分析:
①第11行:為bean的自定義屬性賦值,轉向BeanDefinitionParserDelegate的decorateIfRequired方法:
1 public BeanDefinitionHolder decorateIfRequired( 2 Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) { 3 4 String namespaceUri = getNamespaceURI(node); 5 if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) { 6 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); 7 if (handler != null) { 8 BeanDefinitionHolder decorated = 9 handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd)); 10 if (decorated != null) { 11 return decorated; 12 } 13 } 14 else if (namespaceUri.startsWith("http://www.springframework.org/")) { 15 error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node); 16 } 17 else { 18 // A custom namespace, not to be handled by Spring - maybe "xml:...". 19 if (logger.isDebugEnabled()) { 20 logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]"); 21 } 22 } 23 } 24 return originalDef; 25 }
分析:
①第6行:取出bean空間的解析器。
②第9行:進行bean自定義屬性賦值,轉向SimplePropertyNamespaceHandler的decorate方法:
1 public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) { 2 if (node instanceof Attr) { 3 Attr attr = (Attr) node; 4 String propertyName = parserContext.getDelegate().getLocalName(attr); 5 String propertyValue = attr.getValue(); 6 MutablePropertyValues pvs = definition.getBeanDefinition().getPropertyValues(); 7 if (pvs.contains(propertyName)) { 8 parserContext.getReaderContext().error("Property '" + propertyName + "' is already defined using " + 9 "both <property> and inline syntax. Only one approach may be used per property.", attr); 10 } 11 if (propertyName.endsWith(REF_SUFFIX)) { 12 propertyName = propertyName.substring(0, propertyName.length() - REF_SUFFIX.length()); 13 pvs.add(Conventions.attributeNameToPropertyName(propertyName), new RuntimeBeanReference(propertyValue)); 14 } 15 else { 16 pvs.add(Conventions.attributeNameToPropertyName(propertyName), propertyValue); 17 } 18 } 19 return definition; 20 }
分析:
該函式功能比較簡單,從程式碼中可直接知曉:從節點中取出屬性的名稱和值,然後封裝到MutablePropertyValues中,MutablePropertyValues是BeanDefinitionHolder的一個屬性,這樣就將屬性值帶出去了。
在將bean的自定義屬性封裝後,將返回到DefaultBeanDefinitionDocumentReader的processBeanDefinition函式中:
1 try { 2 // Register the final decorated instance. 3 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); 4 } 5 catch (BeanDefinitionStoreException ex) { 6 getReaderContext().error("Failed to register bean definition with name '" + 7 bdHolder.getBeanName() + "'", ele, ex); 8 } 9 // Send registration event. 10 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); 11 }
至此,整個bean解析階段已走完,大致過程就是將xml檔案流根據不同配置進行各種解析,最終得到BeanDefinitionHolder,接下來進入bean註冊階段。
下面給出解析bean階段的大致時序圖:
by Shawn Chen,2018.12.5日,下午。