spring中的标签分为默认标签和自定义标签,这两种标签的加载方式是不一样的这里主要还是说一下默认标签的加载方式.
并且基础的标签只有四种分别是:import,alias,beans,bean;
spring的实现代码在package org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader;
内.
Element ele
:spring加载XML文件得到的标签对象;
BeanDefinitionParserDelegate delegate:这时一个解析XMLBean的委托类,里面定义了后续对默认标签的处理方法.
当然这几个标签中最重要的还是bean,所以我们看一下这个这个方法中是如何处理bean这个标签的,这个processBeanDefinition()
方法;
这个方法中做了这么几件事:
1.解析标签:通过parseBeanDefinitionElement(ele)
获取到一个BeanDefinitionHolder
对象
2.对获取到的BeanDefinitionHolder
对象,在对自定义的标签进行验证,解析.
3.将解析完成的bean,进行注册.
4.发出注册事件,告诉监听器们这次注册已经完成了;
第2步中是如何解析的
1.首先他获取了标签的id,name,并且将名字按一定的规则截取.
2.对bean的name做唯一性检查
3.解析标签
4.获取bean对应的名称,可以是bean对应的className,在重复的情况下适当加后缀之类的加以区别,保证唯一性.
第3步中的解析的源码
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
parseMetaElements(ele, bd);
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
parseConstructorArgElements(ele, bd);
parsePropertyElements(ele, bd);
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
让我们分析一下整个解析过程;
1.
this.parseState.push(new BeanEntry(beanName));
这个方法是将beanName推到堆栈顶部.这里有源码注释
2.获取className
3.获取parent名称
4.根据拿到className和parent创建bean
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
5.给刚创建的bean赋值,也就是初始化刚才创建的bean
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
6.解析eLookupOverrideSub的子元素
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
7.解析ReplacedMethodSub的给定bean元素
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
8.解析ConstructorArg的子元素
parseConstructorArgElements(ele, bd);
9.解析Property子元素。
parsePropertyElements(ele, bd);
10.对给定bean元素的解析Qualifier子元素。
parseQualifierElements(ele, bd);
11.将上下文中的资源,原始数据set进去,return处理完毕的AbstractBeanDefinition
对象.
(是不是感觉,这样看下来其实也没什么看不懂的,觉得不够详细的同学可以自己点击在看一下,其实并没有现象中的那么复杂)