1. 程式人生 > >【spring原始碼分析】IOC容器初始化(二)

【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) throws
BeanDefinitionStoreException { 2 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); 3 int countBefore = getRegistry().getBeanDefinitionCount(); 4 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); 5 return
getRegistry().getBeanDefinitionCount() - countBefore; 6 }

分析:

①第2行:首先建立一個BeanDefinitionDocumentReader。

②第3行:取出容器中之前例項化的bean的個數。

③第4行:進入具體解析階段。轉向DefaultBeanDefinitionDocumentReaderregisterBeanDefinitions方法:

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行:進入DefaultBeanDefinitionDocumentReaderdoRegisterBeanDefinitions方法:

 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行:如果為元素為預設空間,則轉向DefaultBeanDefinitionDocumentReaderparseDefaultElement方法:

 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行:轉向DefaultBeanDefinitionDocumentReaderprocessBeanDefinition函式:

 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行中,通過委託這裡會轉向BeanDefinitionParserDelegateparseBeanDefinitionElement方法(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行:進行元素的解析,BeanDefinitionParserDelegateparseBeanDefinitionElement方法(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,最終會轉向BeanDefinitionReaderUtilscreateBeanDefinition方法:

 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的自定義屬性值賦值,這裡會轉向BeanDefinitionParserDelegatedecorateBeanDefinitionIfRequired方法:

 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的自定義屬性賦值,轉向BeanDefinitionParserDelegatedecorateIfRequired方法:

 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自定義屬性賦值,轉向SimplePropertyNamespaceHandlerdecorate方法:

 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日,下午。