Spring源码学习笔记

Posted DarkFuture

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码学习笔记相关的知识,希望对你有一定的参考价值。

 


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                         //Spring源码学习笔记

Spring源码学习笔记

Spring源码学习笔记

Spring源码学习笔记1

spring学习笔记源码剖析

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段