Spring源码学习笔记(5)



Spring源码学习笔记(五)

  前言--

    最近花了些时间看了《Spring源码深度解析》这本书,算是入门了Spring的源码吧。打算写下系列文章,回忆一下书的内容,总结代码的运行流程。推荐那些和我一样没接触过SSH框架源码又想学习的,阅读郝佳编著的《Spring源码深度解析》这本书,会是个很好的入门



    写下一句话,开篇不尴尬  ----  上篇文章中梳理到 Spring 加载资源文件后开始解析 Bean, 现在我们从两个解析函数 parseDefaultElement() parseCustomElement() 开始继续回顾。



解析默认标签  parseDefaultElement()

    先来看看 parseDefaultElement() 实现逻辑:

 1     private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
 2         if(delegate.nodeNameEquals(ele, "import")) {
 3             //第一步:  处理 import 标签
 4             this.importBeanDefinitionResource(ele);
 5         } else if(delegate.nodeNameEquals(ele, "alias")) {
 6             //第二步:  处理 alias 标签
 7             this.processAliasRegistration(ele);
 8         } else if(delegate.nodeNameEquals(ele, "bean")) {
 9             //第三步:  处理 bean 标签  =============== 重点
10             this.processBeanDefinition(ele, delegate);
11         } else if(delegate.nodeNameEquals(ele, "beans")) {
12             //第四步:  处理 beans 标签
13             this.doRegisterBeanDefinitions(ele);
14         }
15
16     }

    呵呵哈, 什么都没写, 接着往下看, 一个个分析四中标签的解析。



一:bean 标签

    processBeanDefinition() 方法的逻辑:

 1     protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
 2         //第一步:  BeanDefinitionHolder  类的封装
 3         BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
 4         if(bdHolder != null) {
 5             //第二步:  自定义属性的处理
 6             bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
 7
 8             try {
 9               //第三步;  注册 bean
10                 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
11             } catch (BeanDefinitionStoreException var5) {
12                 this.getReaderContext().error("Failed to register bean definition with name ‘" + bdHolder.getBeanName() + "‘", ele, var5);
13             }
14             //第四步:  发布事件
15             this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
16         }
17
18     }

    首先看第一步中,  BeanDefinitionParserDelegate 类的 parseBeanDefinitionElement() 方法:

1     public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
2         return this.parseBeanDefinitionElement(ele, (BeanDefinition)null);
3     }
 1     public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
 2         //第一步:  解析 id 和 name 属性
 3         String id = ele.getAttribute("id");
 4         String nameAttr = ele.getAttribute("name");
 5         List<String> aliases = new ArrayList();
 6         if(StringUtils.hasLength(nameAttr)) {
 7             //第二步:  分割了 name 属性
 8             String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
 9             aliases.addAll(Arrays.asList(nameArr));
10         }
11
12         String beanName = id;
13         if(!StringUtils.hasText(id) && !aliases.isEmpty()) {
14             beanName = (String)aliases.remove(0);
15
16         }
17
18         if(containingBean == null) {
19             this.checkNameUniqueness(beanName, aliases, ele);
20         }
21         //第三步:  解析属性, 封装到 GenericBeanDefinition 类中
22         AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
23         if(beanDefinition != null) {
24             //第四步:  没有指定 beanName , 生成 beanName
25             if(!StringUtils.hasText(beanName)) {
26                 try {
27                     if(containingBean != null) {
28                         beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
29                     } else {
30                         beanName = this.readerContext.generateBeanName(beanDefinition);
31                         String beanClassName = beanDefinition.getBeanClassName();
32                         if(beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
33                             aliases.add(beanClassName);
34                         }
35                     }
36                 } catch (Exception var9) {
37                     this.error(var9.getMessage(), ele);
38                     return null;
39                 }
40             }
41
42             String[] aliasesArray = StringUtils.toStringArray(aliases);
43             //第五步:  beanDefinition 封装到 BeanDefinitionHolder中
44             return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
45         } else {
46             return null;
47         }
48     }
    在 parseBeanDefinitionElement() 方法中, 主要的是第二步解析属性 parseBeanDefinitionElement() 方法:
 1     public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
 2         this.parseState.push(new BeanEntry(beanName));
 3         String className = null;
 4         if(ele.hasAttribute("class")) {
 5              //第一步:  解析 class 属性
 6             className = ele.getAttribute("class").trim();
 7         }
 8
 9         try {
10             String parent = null;
11             if(ele.hasAttribute("parent")) {
12                 parent = ele.getAttribute("parent");
13             }
14             //第二步:  封装 AbstractBeanDefinition 的 GenericBeanDefinition
15             AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
16             this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);   /** 解析属性 */
17            //第三步:  设置 description 属性 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
18             //第四步:  解析 元数据
19             this.parseMetaElements(ele, bd);
20             //第五步:  解析 lookup-method 属性
21             this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
22             //第六步:  解析 replaced-method 属性
23             this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
24             //第七步:  解析 构造函数 参数
25             this.parseConstructorArgElements(ele, bd);
26             //第八步:  解析 property 元素
27             this.parsePropertyElements(ele, bd);
28             //第九步:  解析 qualifier 元素
29             this.parseQualifierElements(ele, bd);
30             bd.setResource(this.readerContext.getResource());
31             bd.setSource(this.extractSource(ele));
32             AbstractBeanDefinition var7 = bd;
33             return var7;
34         }
35         /** 省略了 catch 语句 */
36         finally {
37             this.parseState.pop();
38         }
39
40         return null;
41     }

    接下来详细说明  parseBeanDefinitionElement() 方法的步骤, 因为很多, 开一个新行,虽然很多, 但是总体的思路还是很清晰的, 就一类元素有对应的解析的方法, 不要乱了阵脚, 战略上藐视一下。  o(* ̄︶ ̄*)o



parseBeanDefinitionElement() 中的方法 :

  (一)  createBeanDefinition()

    首先了解一下各种 BeanDefinition 之间的关系:

    

    XML 文件当中的 <bean> 解析之后, 封装成 BeanDefinition 对象, 并注册到 BeanDefinitionRegistry 类中, 主要以 map 的方式保存, 并为后续的操作所使用。

    然后在来看看 createBeanDefinition() 方法的实现逻辑:

1     protected AbstractBeanDefinition createBeanDefinition(String className, String parentName) throws ClassNotFoundException {
2         return BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader());
3     }
 1     public static AbstractBeanDefinition createBeanDefinition(String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {
 2         //第一步: 封装的 GenericBeanDefinition  实例
 3         GenericBeanDefinition bd = new GenericBeanDefinition();
 4         bd.setParentName(parentName);
 5         if(className != null) {
 6             if(classLoader != null) {
 7                 //第二步:  存在 classLoader ,则反射创建实例
 8                 bd.setBeanClass(ClassUtils.forName(className, classLoader));
 9             } else {
10                 //第三步:  不存在 clasLoader ,只能记录一下 name 了
11                 bd.setBeanClassName(className);
12             }
13         }
14
15         return bd;
16     }

  (二) parseBeanDefinitionAttributes()

     对 element 的属性进行解析的实现逻辑:

 1     public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) {
 2         //第一步:  解析 scope 属性
 3         if(ele.hasAttribute("scope")) {
 4             bd.setScope(ele.getAttribute("scope"));
 5         } else if(containingBean != null) {
 6             bd.setScope(containingBean.getScope());
 7         }
 8         //第二步:  解析 abstract 属性
 9         if(ele.hasAttribute("abstract")) {
10             bd.setAbstract("true".equals(ele.getAttribute("abstract")));
11         }
12         //第三步:  解析 lazy-init 属性
13         String lazyInit = ele.getAttribute("lazy-init");
14         if("default".equals(lazyInit)) {
15             lazyInit = this.defaults.getLazyInit();
16         }
17
18         bd.setLazyInit("true".equals(lazyInit));
19         //第四步:  解析 autowire 属性
20         String autowire = ele.getAttribute("autowire");
21         bd.setAutowireMode(this.getAutowireMode(autowire));
22         //第五步:  解析 dependency-check 属性
23         String dependencyCheck = ele.getAttribute("dependency-check");
24         bd.setDependencyCheck(this.getDependencyCheck(dependencyCheck));
25         //第六步:  解析 depends-on 属性
26         String autowireCandidate;
27         if(ele.hasAttribute("depends-on")) {
28             autowireCandidate = ele.getAttribute("depends-on");
29             bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; "));
30         }
31         //第七步:  解析 autowire-candidate 属性
32         autowireCandidate = ele.getAttribute("autowire-candidate");
33         String destroyMethodName;
34         if(!"".equals(autowireCandidate) && !"default".equals(autowireCandidate)) {
35             bd.setAutowireCandidate("true".equals(autowireCandidate));
36         } else {
37             destroyMethodName = this.defaults.getAutowireCandidates();
38             if(destroyMethodName != null) {
39                 String[] patterns = StringUtils.commaDelimitedListToStringArray(destroyMethodName);
40                 bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
41             }
42         }
43         //第八步:  解析 primary 属性
44         if(ele.hasAttribute("primary")) {
45             bd.setPrimary("true".equals(ele.getAttribute("primary")));
46         }
47         //第九步:  解析 init-method 属性
48         if(ele.hasAttribute("init-method")) {
49             destroyMethodName = ele.getAttribute("init-method");
50             if(!"".equals(destroyMethodName)) {
51                 bd.setInitMethodName(destroyMethodName);
52             }
53         } else if(this.defaults.getInitMethod() != null) {
54             bd.setInitMethodName(this.defaults.getInitMethod());
55             bd.setEnforceInitMethod(false);
56         }
57         //第十步:  解析 destroy-method 属性
58         if(ele.hasAttribute("destroy-method")) {
59             destroyMethodName = ele.getAttribute("destroy-method");
60             if(!"".equals(destroyMethodName)) {
61                 bd.setDestroyMethodName(destroyMethodName);
62             }
63         } else if(this.defaults.getDestroyMethod() != null) {
64             bd.setDestroyMethodName(this.defaults.getDestroyMethod());
65             bd.setEnforceDestroyMethod(false);
66         }
67         //第十一步:  解析 destroy-method 属性
68         if(ele.hasAttribute("factory-method")) {
69             bd.setFactoryMethodName(ele.getAttribute("factory-method"));
70         }
71         //第十二步:  解析 factory-bean 属性
72         if(ele.hasAttribute("factory-bean")) {
73             bd.setFactoryBeanName(ele.getAttribute("factory-bean"));
74         }
75
76         return bd;
77     }

    怎么说呢, 天啦噜,一大坨的代码, 然而只是解析了各种各样的属性, 并设置到第一步中创建的 AbstractBeanDefinition 当中。

  (三) parseMetaElements() 

 1     public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
 2         NodeList nl = ele.getChildNodes();
 3         //第一步:  遍历所有的子元素
 4         for(int i = 0; i < nl.getLength(); ++i) {
 5             Node node = nl.item(i);
 6             //第二步:  判断元素的类型
 7             if(this.isCandidateElement(node) && this.nodeNameEquals(node, "meta")) {
 8                 Element metaElement = (Element)node;
 9                 String key = metaElement.getAttribute("key");
10                 String value = metaElement.getAttribute("value");
11                 //第三步:  构造 BeanMetadataAttribute  类
12                 BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
13                 attribute.setSource(this.extractSource(metaElement));
14                 attributeAccessor.addMetadataAttribute(attribute);
15             }
16         }
17
18     }

(四) parseLookupOverrideSubElements() ,  parseReplacedMethodSubElements()

  lookup-method 以及 replaced-method 属性的使用请有事找度娘!!!o(^▽^)o

 1     public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
 2         NodeList nl = beanEle.getChildNodes();
 3         //第一步:  遍历子元素
 4         for(int i = 0; i < nl.getLength(); ++i) {
 5             Node node = nl.item(i);
 6             //第二步:  判断元素的类型
 7             if(this.isCandidateElement(node) && this.nodeNameEquals(node, "lookup-method")) {
 8                 Element ele = (Element)node;
 9                 //第三步:  获取重写的方法
10                 String methodName = ele.getAttribute("name");
11                 String beanRef = ele.getAttribute("bean");
12                 //第四步:  封装为 LookupOverride 类
13                 LookupOverride override = new LookupOverride(methodName, beanRef);
14                 override.setSource(this.extractSource(ele));
15                 overrides.addOverride(override);
16             }
17         }
18
19     }
 1     public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
 2         NodeList nl = beanEle.getChildNodes();
 3         //第一步:  遍历子元素
 4         for(int i = 0; i < nl.getLength(); ++i) {
 5             Node node = nl.item(i);
 6             //第二步:  判断夙愿类型
 7             if(this.isCandidateElement(node) && this.nodeNameEquals(node, "replaced-method")) {
 8                 //第三步: 获取 要替换的方法 和 替换的方法
 9                 Element replacedMethodEle = (Element)node;
10                 String name = replacedMethodEle.getAttribute("name");
11                 String callback = replacedMethodEle.getAttribute("replacer");
12                 //第四步:  封装成 ReplaceOverride 类
13                 ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
14                 //第五步:  方法的参数
15                 List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, "arg-type");
16                 Iterator var11 = argTypeEles.iterator();
17
18                 while(var11.hasNext()) {
19                     Element argTypeEle = (Element)var11.next();
20                     String match = argTypeEle.getAttribute("match");
21                     match = StringUtils.hasText(match)?match:DomUtils.getTextValue(argTypeEle);
22                     if(StringUtils.hasText(match)) {
23                         replaceOverride.addTypeIdentifier(match);
24                     }
25                 }
26
27                 replaceOverride.setSource(this.extractSource(replacedMethodEle));
28                 overrides.addOverride(replaceOverride);
29             }
30         }
31
32     }

  (五) parseConstructorArgElements()

    解析构造函数参数的实现逻辑:

 1     public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
 2         NodeList nl = beanEle.getChildNodes();
 3         //第一步:  遍历所有元素
 4         for(int i = 0; i < nl.getLength(); ++i) {
 5             Node node = nl.item(i);
 6             //第二步:  判断元素类型
 7             if(this.isCandidateElement(node) && this.nodeNameEquals(node, "constructor-arg")) {
 8                 //第三步:  解析构造函数参数
 9                 this.parseConstructorArgElement((Element)node, bd);
10             }
11         }
12
13     }

    前方高能~~~~~ 一大波代码正在来袭!!!

 1     public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
 2         //第一步:  提取 index, type, name 属性
 3         String indexAttr = ele.getAttribute("index");
 4         String typeAttr = ele.getAttribute("type");
 5         String nameAttr = ele.getAttribute("name");
 6         if(StringUtils.hasLength(indexAttr)) {
 7             try {
 8                 int index = Integer.parseInt(indexAttr);
 9                 if(index < 0) {
10                     this.error("‘index‘ cannot be lower than 0", ele);
11                 } else {
12                     try {
13                         this.parseState.push(new ConstructorArgumentEntry(index));
14                         //第二步:  解析 ele 对应的属性元素
15                         Object value = this.parsePropertyValue(ele, bd, (String)null);
16                         //第四步:  封装到 ValueHolder 类中
17                         ValueHolder valueHolder = new ValueHolder(value);
18                         if(StringUtils.hasLength(typeAttr)) {
19                             valueHolder.setType(typeAttr);
20                         }
21
22                         if(StringUtils.hasLength(nameAttr)) {
23                             valueHolder.setName(nameAttr);
24                         }
25
26                         valueHolder.setSource(this.extractSource(ele));
27                         //第五步:  相同参数重复指定的情况处理
28                         if(bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
29                             this.error("Ambiguous constructor-arg entries for index " + index, ele);
30                         } else {
31                         //第六步:  存在 index 属性的情况时, 封装到 BeanDefinition 的 constructorArgumentValues 的 indexedArgumentValue 中
32                             bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
33                         }
34                     } finally {
35                         this.parseState.pop();
36                     }
37                 }
38             } catch (NumberFormatException var19) {
39                 this.error("Attribute ‘index‘ of tag ‘constructor-arg‘ must be an integer", ele);
40             }
41         } else {
42             try {
43                 this.parseState.push(new ConstructorArgumentEntry());
44                 Object value = this.parsePropertyValue(ele, bd, (String)null);
45                 ValueHolder valueHolder = new ValueHolder(value);
46                 if(StringUtils.hasLength(typeAttr)) {
47                     valueHolder.setType(typeAttr);
48                 }
49
50                 if(StringUtils.hasLength(nameAttr)) {
51                     valueHolder.setName(nameAttr);
52                 }
53
54                 valueHolder.setSource(this.extractSource(ele));
55                 //第七步: 不存在 index 属性时, 封装到 BeanDefinition 的 constructorArgumentValues 的 genericArgumentValue 中
56
57           bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
58             } finally {
59                 this.parseState.pop();
60             }
61         }
62
63     }

  (六) parsePropertyValue()

    解析构造函数配置中子元素的实现逻辑,  感觉就是上一步代码没做完的事堆给下一个方法收拾了(*/ω╲*)

 1     public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
 2         String elementName = propertyName != null?"<property> element for property ‘" + propertyName + "‘":"<constructor-arg> element";
 3         NodeList nl = ele.getChildNodes();
 4         Element subElement = null;
 5     //第一步: 遍历所有的子元素
 6         for(int i = 0; i < nl.getLength(); ++i) {
 7             Node node = nl.item(i);
 8             //第二步:  略过 description 和 meta
 9             if(node instanceof Element && !this.nodeNameEquals(node, "description") && !this.nodeNameEquals(node, "meta")) {
10                 if(subElement != null) {
11                     this.error(elementName + " must not contain more than one sub-element", ele);
12                 } else {
13                     subElement = (Element)node;
14                 }
15             }
16         }
17         //第三步:  解析 constructor-arg 上的 ref 和 value 属性   (!! 注意: 不存在 1,既有 ref 又有 vlaue 属性  2,存在 ref 或 value 且还有子元素)
18         boolean hasRefAttribute = ele.hasAttribute("ref");
19         boolean hasValueAttribute = ele.hasAttribute("value");
20         if(hasRefAttribute && hasValueAttribute || (hasRefAttribute || hasValueAttribute) && subElement != null) {
21             this.error(elementName + " is only allowed to contain either ‘ref‘ attribute OR ‘value‘ attribute OR sub-element", ele);
22         }
23
24         if(hasRefAttribute) {
25             String refName = ele.getAttribute("ref");
26             if(!StringUtils.hasText(refName)) {
27                 this.error(elementName + " contains empty ‘ref‘ attribute", ele);
28             }
29             //第四步:  ref 属性使用 RuntimeBeanReference  处理
30             RuntimeBeanReference ref = new RuntimeBeanReference(refName);
31             ref.setSource(this.extractSource(ele));
32             return ref;
33         } else if(hasValueAttribute) {
34             //第五步:  value 属性使用 TypedStringValue  处理
35             TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute("value"));
36             valueHolder.setSource(this.extractSource(ele));
37             return valueHolder;
38         } else if(subElement != null) {
39             //第六步: 解析子元素
40             return this.parsePropertySubElement(subElement, bd);
41         } else {
42             this.error(elementName + " must specify a ref or value", ele);
43             return null;
44         }
45     }

    在 parsePropertyValue() 中, 第六步解析子元素 parsePropertySubElement() 方法的实现:

1     public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
2         return this.parsePropertySubElement(ele, bd, (String)null);
3     }
 1     public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
 2         //第一步:  不是默认命名空间的元素的处理
 3         if(!this.isDefaultNamespace((Node)ele)) {
 4             return this.parseNestedCustomElement(ele, bd);
 5         } else if(this.nodeNameEquals(ele, "bean")) {
 6             //第二步: 对 Bean 元素的处理
 7             BeanDefinitionHolder nestedBd = this.parseBeanDefinitionElement(ele, bd);
 8             if(nestedBd != null) {
 9                 nestedBd = this.decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
10             }
11
12             return nestedBd;
13         } else if(this.nodeNameEquals(ele, "ref")) {
14             //第三步: 对 ref 属性的处理
15             String refName = ele.getAttribute("bean");
16             boolean toParent = false;
17             if(!StringUtils.hasLength(refName)) {
18                 refName = ele.getAttribute("local");
19                 if(!StringUtils.hasLength(refName)) {
20                     refName = ele.getAttribute("parent");
21                     toParent = true;
22                     if(!StringUtils.hasLength(refName)) {
23                         this.error("‘bean‘, ‘local‘ or ‘parent‘ is required for <ref> element", ele);
24                         return null;
25                     }
26                 }
27             }
28
29             if(!StringUtils.hasText(refName)) {
30                 this.error("<ref> element contains empty target attribute", ele);
31                 return null;
32             } else {
33                 RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
34                 ref.setSource(this.extractSource(ele));
35                 return ref;
36             }
37         } else if(this.nodeNameEquals(ele, "idref")) {
38             //第四步:  对 idref 属性的处理
39             return this.parseIdRefElement(ele);
40         } else if(this.nodeNameEquals(ele, "value")) {
41             //第五步:  对 value 属性的处理
42             return this.parseValueElement(ele, defaultValueType);
43         } else if(this.nodeNameEquals(ele, "null")) {
44             //第六步:  对 null 元素的解析
45             TypedStringValue nullHolder = new TypedStringValue((String)null);
46             nullHolder.setSource(this.extractSource(ele));
47             return nullHolder;
48         }
49            //第七步:  对各种集合属性的解析
50            else if(this.nodeNameEquals(ele, "array")) {
51             return this.parseArrayElement(ele, bd);
52         } else if(this.nodeNameEquals(ele, "list")) {
53             return this.parseListElement(ele, bd);
54         } else if(this.nodeNameEquals(ele, "set")) {
55             return this.parseSetElement(ele, bd);
56         } else if(this.nodeNameEquals(ele, "map")) {
57             return this.parseMapElement(ele, bd);
58         } else if(this.nodeNameEquals(ele, "props")) {
59             return this.parsePropsElement(ele);
60         } else {
61             this.error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
62             return null;
63         }
64     }

  (七) parsePropertyElements()

    解析 <property> 元素的实现逻辑:

 1     public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
 2         NodeList nl = beanEle.getChildNodes();
 3         //第一步:  遍历所有的属性
 4         for(int i = 0; i < nl.getLength(); ++i) {
 5             Node node = nl.item(i);
 6             //第二步: 判断元素的类型
 7             if(this.isCandidateElement(node) && this.nodeNameEquals(node, "property")) {
 8                 this.parsePropertyElement((Element)node, bd);
 9             }
10         }
11
12     }
 1    public void parsePropertyElement(Element ele, BeanDefinition bd) {
 2         //第一步:  获取 name 属性
 3         String propertyName = ele.getAttribute("name");
 4         if(!StringUtils.hasLength(propertyName)) {
 5             this.error("Tag ‘property‘ must have a ‘name‘ attribute", ele);
 6         } else {
 7             this.parseState.push(new PropertyEntry(propertyName));
 8
 9             try {
10                 //第二步:  处理同一属性多次配置的情况
11                 if(bd.getPropertyValues().contains(propertyName)) {
12                     this.error("Multiple ‘property‘ definitions for property ‘" + propertyName + "‘", ele);
13                     return;
14                 }
15                 //第三步:  解析元素属性
16                 Object val = this.parsePropertyValue(ele, bd, propertyName);
17                 PropertyValue pv = new PropertyValue(propertyName, val);
18                 this.parseMetaElements(ele, pv);
19                 pv.setSource(this.extractSource(ele));
20                 //第四步:  添加属性
21           bd.getPropertyValues().addPropertyValue(pv);
22             } finally {
23                 this.parseState.pop();
24             }
25
26         }
27     }

  (八) parseQualifierElements()

    解析 qualifier 属性的实现逻辑:

 1     public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
 2         //第一步:  获取 type 属性
 3         String typeName = ele.getAttribute("type");
 4         if(!StringUtils.hasLength(typeName)) {
 5             this.error("Tag ‘qualifier‘ must have a ‘type‘ attribute", ele);
 6         } else {
 7             this.parseState.push(new QualifierEntry(typeName));
 8
 9             try {
10                 //第二步: 封装的 AutowireCandidateQualifier 类
11                 AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);
12                 qualifier.setSource(this.extractSource(ele));
13                 String value = ele.getAttribute("value");
14                 if(StringUtils.hasLength(value)) {
15                     qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
16                 }
17
18                 NodeList nl = ele.getChildNodes();
19                 //第三步:  遍历所有的子元素
20                 for(int i = 0; i < nl.getLength(); ++i) {
21                     Node node = nl.item(i);
22                      //第四步:  判断子元素的类型
23                     if(this.isCandidateElement(node) && this.nodeNameEquals(node, "attribute")) {
24                         Element attributeEle = (Element)node;
25                         String attributeName = attributeEle.getAttribute("key");
26                         String attributeValue = attributeEle.getAttribute("value");
27                         if(!StringUtils.hasLength(attributeName) || !StringUtils.hasLength(attributeValue)) {
28                             this.error("Qualifier ‘attribute‘ tag must have a ‘name‘ and ‘value‘", attributeEle);
29                             return;
30                         }
31                         //第五步:  封装的 BeanMetadataAttribute 类性
32                         BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
33                         attribute.setSource(this.extractSource(attributeEle));
34                         //第六步:  qualifier 添加属性
35                         qualifier.addMetadataAttribute(attribute);
36                     }
37                 }
38
39                 bd.addQualifier(qualifier);
40             } finally {
41                 this.parseState.pop();
42             }
43         }
44     }

    到此, 我们大致涵盖了 processBeanDefinition() 方法当中的第一步 delegate.parseBeanDefinitionElement() 方法的实现逻辑。 绝望, 这么长的代码总结起来就一句代码而已!! ?(T?T)

    在 processBeanDefinition() 方法中, 第二步实现 自定义元素的解析 decorateBeanDefinitionIfRequired() 的逻辑:

1     public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
2         return this.decorateBeanDefinitionIfRequired(ele, definitionHolder, (BeanDefinition)null);
3     }
 1     public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
 2         BeanDefinitionHolder finalDefinition = definitionHolder;
 3         NamedNodeMap attributes = ele.getAttributes();
 4         //第一步:  遍历所有的 子元素
 5         for(int i = 0; i < attributes.getLength(); ++i) {
 6             Node node = attributes.item(i);
 7             finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
 8         }
 9
10         NodeList children = ele.getChildNodes();
11         //第二步:  遍历所有的 子节点
12         for(int i = 0; i < children.getLength(); ++i) {
13             Node node = children.item(i);
14             if(node.getNodeType() == 1) {
15                 finalDefinition = this.decorateIfRequired(node, finalDefinition, containingBd);
16             }
17         }
18
19         return finalDefinition;
20     }
 1     public BeanDefinitionHolder decorateIfRequired(Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
 2         String namespaceUri = this.getNamespaceURI(node);
 3         //第一步:  对非默认命名空间标签的处理
 4         if(!this.isDefaultNamespace(namespaceUri)) {
 5             //第二步:  根据命名空间找到对应的处理器调用方法
 6             NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
 7             if(handler != null) {
 8                 //第三步:  进行修饰
 9                 return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
10             }
11
12             if(namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) {
13                 this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
14             } else if(this.logger.isDebugEnabled()) {
15                 this.logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
16             }
17         }
18
19         return originalDef;
20     }

1     public String getNamespaceURI(Node node) {  return node.getNamespaceURI(); }                                                                   

1     public boolean isDefaultNamespace(String namespaceUri) {
2         return !StringUtils.hasLength(namespaceUri) || "http://www.springframework.org/schema/beans".equals(namespaceUri);
3     }

    在 processBeanDefinition() 方法中, 第三步注册 BeanDefinition 的 registerBeanDefinition() 方法的实现逻辑

 1     public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
 2
 3         String beanName = definitionHolder.getBeanName();
 4         //第一步:  使用 beanName 做标志
 5         registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
 6
 7         String[] aliases = definitionHolder.getAliases();
 8         if(aliases != null) {
 9             String[] var4 = aliases;
10             int var5 = aliases.length;
11
12             for(int var6 = 0; var6 < var5; ++var6) {
13                 String aliase = var4[var6];
14                 //第二步:  注册所有别名
15                 registry.registerAlias(beanName, aliase);
16             }
17         }
18
19     }

    在 registerBeanDefinition() 方法中, 第一步使用 beanName 作为 BeanDefinition 的标志注册, 实现的逻辑:

 1     public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
 2
 3         if(beanDefinition instanceof AbstractBeanDefinition) {
 4             try {
 5                 //第一步:  对 AbstractBeanDefinition 的 methodOverrides  的校验
 6                 ((AbstractBeanDefinition)beanDefinition).validate();
 7             } catch (BeanDefinitionValidationException var7) {
 8                 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var7);
 9             }
10         }
11
12         Map var3 = this.beanDefinitionMap;
13         //第二步:  对全局变量进行同步
14         synchronized(this.beanDefinitionMap) {
15             //第三步:  缓存中获取 BeanDefinition
16             BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
17             if(oldBeanDefinition != null) {
18                 if(!this.allowBeanDefinitionOverriding) {
19                     throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean ‘" + beanName + "‘: There is already [" + oldBeanDefinition + "] bound.");
20                 }
21
22                 if(oldBeanDefinition.getRole() < beanDefinition.getRole()) {
23                     if(this.logger.isWarnEnabled()) {
24                         this.logger.warn("Overriding user-defined bean definition for bean ‘" + beanName + " with a framework-generated bean definition ‘: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
25                     }
26                 } else if(this.logger.isInfoEnabled()) {
27                     this.logger.info("Overriding bean definition for bean ‘" + beanName + "‘: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
28                 }
29             } else {
30                 //第四步:  记录 beanName
31                 this.beanDefinitionNames.add(beanName);
32                 this.frozenBeanDefinitionNames = null;
33             }
34             //第五步:  注册 beanDefinition, 放入到 Map 集合中
35             this.beanDefinitionMap.put(beanName, beanDefinition);
36         }
37
38         this.resetBeanDefinition(beanName);
39     }

    本来想把 logger 还有 exception 信息都去掉, 但是看了一下, 里面的内容说明了许多问题, 对梳理逻辑很有帮助, 看这段代码的时候应该过一遍。

    在 registerBeanDefinition() 方法中, 第二步使用 别名注册 BeanDefinition 的 registerAlias() 方法的实现逻辑:

 1     public void registerAlias(String name, String alias) {
 2         //第一步:  beanName 和 alias 相同, 则删除对应的 alias
 3         if(alias.equals(name)) {
 4             this.aliasMap.remove(alias);
 5         } else {
 6             if(!this.allowAliasOverriding()) {
 7                 String registeredName = (String)this.aliasMap.get(alias);
 8                 if(registeredName != null && !registeredName.equals(name)) {
 9                     throw new IllegalStateException("Cannot register alias ‘" + alias + "‘ for name ‘" + name + "‘: It is already registered for name ‘" + registeredName + "‘.");
10                 }
11             }
12
13             this.checkForAliasCircle(name, alias);
14             //第二步:  注册 Alias
15             this.aliasMap.put(alias, name);
16         }
17
18     }

    在 processBeanDefinition() 方法中,  第四步通知完成注册的方法 fireComponentRegistered() 方法, 留给子类扩展。



 

  二 :  alias 标签

    是不是觉得有点奔溃, 到现在为止只是解决了一个 <bean> 标签的处理。  但是, 但是来了,接下来剩下的标签的处理相对于 <bean> 标签的处理要简单得多得多得多。

    在 parseDefaultElement() 方法中, 第二步 processAliasRegistration() 方法的实现逻辑:

 1     protected void processAliasRegistration(Element ele) {
 2         //第一步:  获取 beanName 和 alias 属性
 3         String name = ele.getAttribute("name");
 4         String alias = ele.getAttribute("alias");
 5         boolean valid = true;
 6         if(!StringUtils.hasText(name)) {
 7             this.getReaderContext().error("Name must not be empty", ele);
 8             valid = false;
 9         }
10
11         if(!StringUtils.hasText(alias)) {
12             this.getReaderContext().error("Alias must not be empty", ele);
13             valid = false;
14         }
15
16         if(valid) {
17             try {
18             //第二步:  注册 alias
19                 this.getReaderContext().getRegistry().registerAlias(name, alias);
20             } catch (Exception var6) {
21                 this.getReaderContext().error("Failed to register alias ‘" + alias + "‘ for bean with name ‘" + name + "‘", ele, var6);
22             }
23             //第三步:  注册完成后的通知事件
24             this.getReaderContext().fireAliasRegistered(name, alias, this.extractSource(ele));
25         }
26
27     }


  三  : import 标签

    在 parseDefaultElement() 方法中, 在第一步解析 import 标签的 importBeanDefinitionResource() 的方法的实现:

 1     protected void importBeanDefinitionResource(Element ele) {
 2         //第一步:  获取 resource 属性
 3         String location = ele.getAttribute("resource");
 4         if(!StringUtils.hasText(location)) {
 5             this.getReaderContext().error("Resource location must not be empty", ele);
 6         } else {
 7             //第二步:  处理 placeHolder 的情况
 8             location = this.environment.resolveRequiredPlaceholders(location);
 9             Set<Resource> actualResources = new LinkedHashSet(4);
10             //第三步:  判断是相对路径还是绝对路径
11             boolean absoluteLocation = false;
12
13             try {
14                 absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
15             } catch (URISyntaxException var11) {
16                 ;
17             }
18
19             int importCount;
20             if(absoluteLocation) {
21                 try {
22                     //第四步:  是绝对路径,直接加载 配置文件
23                     importCount = this.getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
24                 } catch (BeanDefinitionStoreException var10) {
25                     this.getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, var10);
26                 }
27             } else {
28                 try {
29                     //第五步:  相对路径计算出绝对路径, 加载配置文件
30                     Resource relativeResource = this.getReaderContext().getResource().createRelative(location);
31                     if(relativeResource.exists()) {
32                         importCount = this.getReaderContext().getReader().loadBeanDefinitions(relativeResource);
33                         actualResources.add(relativeResource);
34                     } else {
35                         String baseLocation = this.getReaderContext().getResource().getURL().toString();
36                         //第六步:  使用默认 ResourcePatternResolver 进行解析
37                         importCount = this.getReaderContext().getReader().loadBeanDefinitions(StringUtils.applyRelativePath(baseLocation, location), actualResources);
38                     }
39
40             }
41
42             Resource[] actResArray = (Resource[])actualResources.toArray(new Resource[actualResources.size()]);
43             //第七步:  通知监听器
44             this.getReaderContext().fireImportProcessed(location, actResArray, this.extractSource(ele));
45         }
46     }


四 : beans 标签

    接触过 Spring 的都熟悉 <beans> 标签了, 在  中解析的 <bean> 标签, 递归调用 bean 标签的解析方法。 轻松略过.  哈哈哈哈哈 ( ^_^ )



解析自定义标签  parseCustomElement()

    解析自定义标签的方法 parseCustomElement() 方法的实现逻辑:

1     public BeanDefinition parseCustomElement(Element ele) {
2         return this.parseCustomElement(ele, (BeanDefinition)null);
3     }
 1     public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
 2         //第一步:  获取对应的命名空间
 3         String namespaceUri = this.getNamespaceURI(ele);
 4         //第二步:  根据命名空间找到 NamespaceHandler
 5         NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
 6         if(handler == null) {
 7             this.error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
 8             return null;
 9         } else {
10             //第三步:  调用自定义的 handler 的方法
11             return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
12         }
13     }

    在 parseCustomElement() 方法中, 第二步 获取 NamespaceHandler 方法中, readerContext 把 namespaceHandlerResolver 初始化为 DefaultNamespaceHandlerResolver :

 1     public NamespaceHandler resolve(String namespaceUri) {
 2         //第一步:  获取所有配置的 handler
 3         Map<String, Object> handlerMappings = this.getHandlerMappings();
 4         //第二步:  获取类名
 5         Object handlerOrClassName = handlerMappings.get(namespaceUri);
 6         if(handlerOrClassName == null) {
 7             return null;
 8         } else if(handlerOrClassName instanceof NamespaceHandler) {
 9             //第三步:  已解析的情况, 从缓存中获取
10             return (NamespaceHandler)handlerOrClassName;
11         } else {
12             //第四步:  未解析, 通过类路径, 反射创建类实例
13             String className = (String)handlerOrClassName;
14
15             try {
16                 Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
17                 if(!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
18                     throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
19                 } else {
20                     //第五步:  初始化类
21                     NamespaceHandler namespaceHandler = (NamespaceHandler)BeanUtils.instantiateClass(handlerClass);
22                     //第六步:  调用 NamespaceHandler 的初始化方法
23                     namespaceHandler.init();
24                     //第七步:  记录在缓存当中
25                     handlerMappings.put(namespaceUri, namespaceHandler);
26                     return namespaceHandler;
27                 }
28             }
29         }
30     }

    结合注释, 还是挺简单的一段代码来着的, 初始化一个 NamespaceHandler 类, 缓存也只是把类记录在一个 Map 对象中。

    在 resolve() 方法中, 第一步 getHandlerMappings() 方法获取所有配置的 handler 的实现逻辑:

 1     private Map<String, Object> getHandlerMappings() {
 2         //第一步:  没有缓存则进行缓存    (缓存就是 handlerMappings 属性)
 3         if(this.handlerMappings == null) {
 4             synchronized(this) {
 5                 if(this.handlerMappings == null) {
 6                     try {
 7                         //第二步:  加载配置文件
 8                         Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
 9                         if(this.logger.isDebugEnabled()) {
10                             this.logger.debug("Loaded NamespaceHandler mappings: " + mappings);
11                         }
12
13                         Map<String, Object> handlerMappings = new ConcurrentHashMap(mappings.size());
14                         //第三步:  将配置文件 Properties 文件合并到 handlerMappings 中
15                         CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
16                         this.handlerMappings = handlerMappings;
17                     }
18                 }
19             }
20         }
21
22         return this.handlerMappings;
23     }

    关于加载的配置文件, 在  DefaultNamespaceHandlerResolver 类的构造函数中, 把 this.handlerMappingsLocation 初始化为 META-INF/spring.handlers:

 1     public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
 2
 3
 4
 5     public DefaultNamespaceHandlerResolver(ClassLoader classLoader, String handlerMappingsLocation) {
 6         this.logger = LogFactory.getLog(this.getClass());
 7         Assert.notNull(handlerMappingsLocation, "Handler mappings location must not be null");
 8         this.classLoader = classLoader != null?classLoader:ClassUtils.getDefaultClassLoader();
 9         //第一步:  初始化
10         this.handlerMappingsLocation = handlerMappingsLocation;
11     }

    然后, 我们瞄一眼 spring.handlers 配置文件:

1   http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
2   http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
3   http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler

    在  parseCustomElement() 方法中, 第三步调用 handler 的 parse() 方法的实现逻辑, 以 NamespaceHandlerSupport 类的实现为例:

1     public BeanDefinition parse(Element element, ParserContext parserContext) {
2         return this.findParserForElement(element, parserContext).parse(element, parserContext);
3     }
 1     private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
 2         //第一步:  获取元素的名称
 3         String localName = parserContext.getDelegate().getLocalName(element);
 4         //第二步:  根据名称获取对应的解析器
 5         BeanDefinitionParser parser = (BeanDefinitionParser)this.parsers.get(localName);
 6         if(parser == null) {
 7             parserContext.getReaderContext().fatal("Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
 8         }
 9
10         return parser;
11     }

    对于 parse() 方法, 在  AbstractBeanDefinitionParser 中找到了其实现方法:

 1     public final BeanDefinition parse(Element element, ParserContext parserContext) {
 2         //第一步:  调用自定义的解析函数
 3         AbstractBeanDefinition definition = this.parseInternal(element, parserContext);
 4         if(definition != null && !parserContext.isNested()) {
 5             try {
 6                 //第二步:  获取 id 属性
 7                 String id = this.resolveId(element, definition, parserContext);
 8                 if(!StringUtils.hasText(id)) {
 9                     parserContext.getReaderContext().error("Id is required for element ‘" + parserContext.getDelegate().getLocalName(element) + "‘ when used as a top-level tag", element);
10                 }
11
12                 String[] aliases = new String[0];
13                 //第三步:  获取 name 属性
14                 String name = element.getAttribute("name");
15                 if(StringUtils.hasLength(name)) {
16                     aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
17                 }
18                 //第四步: AbstractBeanDefinition 转换为 BeanDefinitionHolder 对象
19
20                 BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
21                 this.registerBeanDefinition(holder, parserContext.getRegistry());
22                 if(this.shouldFireEvents()) {
23                     //第五步:  通知监听器
24                     BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
25                     this.postProcessComponentDefinition(componentDefinition);
26                     parserContext.registerComponent(componentDefinition);
27                 }
28             } catch (BeanDefinitionStoreException var9) {
29                 parserContext.getReaderContext().error(var9.getMessage(), element);
30                 return null;
31             }
32         }
33
34         return definition;
35     }

    看起来很多, 其实只是 AbstractBeanDefinition 转换为 BeanDefinitionHolder 对象, 在 第一步的调用自定义解析函数的 parseInternal() 的实现逻辑, 在 AbstractSingleBeanDefinitionParser 类中找到了还方法的实现 ( AbstractBeanDefinitionParser 中定义该方法, 子类实现):

 1    protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
 2         BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
 3         String parentName = this.getParentName(element);
 4         if(parentName != null) {
 5             builder.getRawBeanDefinition().setParentName(parentName);
 6         }
 7         //第一步:  获取 class 属性
 8         Class<?> beanClass = this.getBeanClass(element);
 9         if(beanClass != null) {
10             builder.getRawBeanDefinition().setBeanClass(beanClass);
11         } else {
12             String beanClassName = this.getBeanClassName(element);
13             if(beanClassName != null) {
14                 builder.getRawBeanDefinition().setBeanClassName(beanClassName);
15             }
16         }
17
18         builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
19         if(parserContext.isNested()) {
20         //第二步:  设置 scope 属性
21             builder.setScope(parserContext.getContainingBeanDefinition().getScope());
22         }
23         //第三步:  设置 lazy-init 属性
24         if(parserContext.isDefaultLazyInit()) {
25             builder.setLazyInit(true);
26         }
27         //第四步:  调用自定义的解析函数
28         this.doParse(element, parserContext, builder);
29         return builder.getBeanDefinition();
30     }

    在 parseInternal() 方法中, 第四步 doParse() 方法才真正调用了我们自己写的解析方法。



    到此,我们已经了解了 Spring 默认标签 以及 自定义标签的处理, 在接下来的内容当中, 将进入 Spring 在加载完 XML 配置文件后, 对 Bean 的初始化的工作。

    ㄟ( ▔, ▔ )ㄏ   来个 Spring 的套路, FIREDAYWORKCOMPLETEDEVENT(new GOODNIGHT("(~﹃~)~zZ"));

时间: 2024-10-23 21:47:30

Spring源码学习笔记(5)的相关文章

Spring源码学习笔记(6)

Spring源码学习笔记(六) 前言-- 最近花了些时间看了<Spring源码深度解析>这本书,算是入门了Spring的源码吧.打算写下系列文章,回忆一下书的内容,总结代码的运行流程.推荐那些和我一样没接触过SSH框架源码又想学习的,阅读郝佳编著的<Spring源码深度解析>这本书,会是个很好的入门. 上一篇中我们梳理到 Spring 加载 XML 配置文件, 完成 XML 的解析工作,接下来我们将进入 Spring 加载 bean 的逻辑. 我们使用 Spring 获取 XML

Spring源码学习笔记(3)

Spring源码学习笔记(三) 前言----     最近花了些时间看了<Spring源码深度解析>这本书,算是入门了Spring的源码吧.打算写下系列文章,回忆一下书的内容,总结代码的运行流程.推荐那些和我一样没接触过SSH框架源码又想学习的,阅读郝佳编著的<Spring源码深度解析>这本书,会是个很好的入门. DispatcherServlet 实现核心功能 和普通的 Servelt 类一样, DispatcherServlet 中的 doGet() 和 doPost() 方法

Spring源码学习笔记(7)

Spring源码学习笔记(七) 前言-- 最近花了些时间看了<Spring源码深度解析>这本书,算是入门了Spring的源码吧.打算写下系列文章,回忆一下书的内容,总结代码的运行流程.推荐那些和我一样没接触过SSH框架源码又想学习的,阅读郝佳编著的<Spring源码深度解析>这本书,会是个很好的入门 写前说句话, 开篇不尴尬 ---- 接下的这一篇当中, 我们将来回顾 Spring 中 AOP 功能的实现流程.  早上精力充沛, 开始新一天的学习 \(^o^)/~ 接触过 Spri

Spring源码学习笔记(1)

SpringMVC源码学习笔记(一) 前言----   最近花了些时间看了<Spring源码深度解析>这本书,算是入门了Spring的源码吧.打算写下系列文章,回忆一下书的内容,总结代码的运行流程.推荐那些和我一样没接触过SSH框架源码又想学习的,阅读郝佳编著的<Spring源码深度解析>这本书,会是个很好的入门.  进入正文,首先贴上SpringMVC的图片(来自https://docs.spring.io/spring/docs/current/spring-framework

Spring源码学习笔记1

1.Spring中最核心的两个类 1)DefaultListableBeanFactory XmlBeanFactory继承自DefaultListableBeanFactory,DefaultListableBeanFactory是整个bean加载的核心部分,是Spring加载及注册bean的默认实现 2)XmlBeanDefinitionReader 2.示例代码 BeanFactory bf=new XmlBeanFactory(new ClassPathResource("beanFac

Spring源码学习-容器BeanFactory(一) BeanDefinition的创建-解析资源文件

写在前面 从大四实习至今已一年有余,作为一个程序员,一直没有用心去记录自己工作中遇到的问题,甚是惭愧,打算从今日起开始养成写博客的习惯.作为一名java开发人员,Spring是永远绕不过的话题,它的设计精巧,代码优美,值得每一名开发人员学习阅读. 在我最开始学习javaEE时,第一次接触Spring是从一个S(Struts)S(Spring)H(Herbinate)的框架开始.由java原生开发到框架开发转换过程中,那时我的印象里Struts负责控制层,herbinate负责数据层,而Sprin

Hadoop源码学习笔记(1) ——第二季开始——找到Main函数及读一读Configure类

Hadoop源码学习笔记(1) ——找到Main函数及读一读Configure类 前面在第一季中,我们简单地研究了下Hadoop是什么,怎么用.在这开源的大牛作品的诱惑下,接下来我们要研究一下它是如何实现的. 提前申明,本人是一直搞.net的,对java略为生疏,所以在学习该作品时,会时不时插入对java的学习,到时也会摆一些上来,包括一下设计模式之类的.欢迎高手指正. 整个学习过程,我们主要通过eclipse来学习,之前已经讲过如何在eclipse中搭建调试环境,这里就不多述了. 在之前源码初

Hadoop源码学习笔记(4) ——Socket到RPC调用

Hadoop源码学习笔记(4) ——Socket到RPC调用 Hadoop是一个分布式程序,分布在多台机器上运行,事必会涉及到网络编程.那这里如何让网络编程变得简单.透明的呢? 网络编程中,首先我们要学的就是Socket编程,这是网络编程中最底层的程序接口,分为服务器端和客户端,服务器负责监听某个端口,客户端负责连接服务器上的某个端口,一旦连接通过后,服务器和客户端就可以双向通讯了,我们看下示例代码: ServerSocket server = new ServerSocket(8111); S

Hadoop源码学习笔记(3) ——初览DataNode及学习线程

Hadoop源码学习笔记(3) ——初览DataNode及学习线程 进入了main函数,我们走出了第一步,接下来看看再怎么走: public class DataNode extends Configured implements InterDatanodeProtocol,       ClientDatanodeProtocol, FSConstants, Runnable {      public static DataNode createDataNode(String args[],