前言--
最近花了些时间看了《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 的初始化的工作。