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源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段