Spring 源码分析之默认标签解析
上一节 我们说到 IOC容器的基本实现,分析到解析标签 :如以下代码
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) { //判断是否使用了默认的命名空间 如果是则,执行一下代码 如果不是 执行自定义标签的解析
NodeList nl = root.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element)node;
if (delegate.isDefaultNamespace(ele)) {
this.parseDefaultElement(ele, delegate);//执行默认标签的解析
} else {
delegate.parseCustomElement(ele);//执行自定义标签的解析
}
}
}
} else {
delegate.parseCustomElement(root);//执行自定义标签的解析
}
}
现在我们就先分析下 执行默认标签的解析:点入parseDefaultElement(ele, delegate)方法
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, "import")) {
this.importBeanDefinitionResource(ele);//解析import 标签
} else if (delegate.nodeNameEquals(ele, "alias")) {
this.processAliasRegistration(ele);//解析alias 标签
} else if (delegate.nodeNameEquals(ele, "bean")) {
this.processBeanDefinition(ele, delegate);//解析bean标签
} else if (delegate.nodeNameEquals(ele, "beans")) {
this.doRegisterBeanDefinitions(ele);//解析beans标签
}
}
如以上我们分析了 Spring解析4种标签:import标签, alias标签, bean标签和beans标签,这里我们重点分析一下 如何解析bean标签
解析bean标签
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);//委托delegate解析
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);//如果beanHolder 不为空 ,则进行装配
try {
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());//开始注册bean
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));//通知监听器以及,这个bean已经加载完成
}
}
1.委托delegate.parseBeanDefinitionElement()方法进行解析,将解析后的值封装到BeanDefinitionHolder 的实例bdHolder中,此时我们的BeanDefintionHolder以及有配置文件中的各个属性了,如Class name id之类的属性
2.如果bean不为空的情况下,若存在bean标签的子节点再有在定义属性,还需要对bean标签再次进行解析
3.解析完成 之后的注册交给了registerBeanDefinition()方法
提取bean信息
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute("id");//提取id
String nameAttr = ele.getAttribute("name");//提取name
List<String> aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
beanName = (String)aliases.remove(0);
if (this.logger.isDebugEnabled()) {
this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
this.checkNameUniqueness(beanName, aliases, ele);
}
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);//提取bean标签的其他属性 进一步封装到GenericbeanDefaintion中
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
} else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} else {
return null;
}
}
1.提取id和name的属性
2.进一步解析其他属性 封装到GenericBeanDefinition类型的实例中
3.检测beanName,如果没有beanName,则默认使用Bean为他生成BeanName
4.将解析出来的信息封装到BeanDefinitionHolder的实例中
解析其他标签的属性
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute("class")) { //解析Class属性
className = ele.getAttribute("class").trim();
}
try {
String parent = null;
if (ele.hasAttribute("parent")) {//解析parent属性
parent = ele.getAttribute("parent");
}
AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);//创建用与承载属性 AbstractBeanDefintion 类型的GenericBeanDefinition实例
//硬编码解析默认bean的各个属性
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//解析Description
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
//解析meta
this.parseMetaElements(ele, bd);
//解析LookUp-method
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析Replaced-method
this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析构造函数参数
this.parseConstructorArgElements(ele, bd);
//解析Property元素
this.parsePropertyElements(ele, bd);
//解析Qualifier子元素
this.parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(this.extractSource(ele));
AbstractBeanDefinition var7 = bd;
return var7;
} catch (ClassNotFoundException var13) {
this.error("Bean class [" + className + "] not found", ele, var13);
} catch (NoClassDefFoundError var14) {
this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
} catch (Throwable var15) {
this.error("Unexpected failure during bean definition parsing", ele, var15);
} finally {
this.parseState.pop();
}
return null;
}
创建用于属性承载的BeanDefinition
beanDefinition 是一个接口 用三种实现 RootBeanDefinition,ChildBeanDefinition以及GenericBeanDefinition 这三种均实现了AbstractBeanDefinitionBean 它们之间的关系如下图:
继承关系.png
由此可见 首先就是要创建 承载属性的实例,也就是创建GenericBeanDefintion 类型的实例
public static AbstractBeanDefinition createBeanDefinition(String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) {
bd.setBeanClass(ClassUtils.forName(className, classLoader));
} else {
bd.setBeanClassName(className); //记录ClassName
}
}
return bd;
}
创建完用于属性承载的BeanDefinition 接下来就是 解析各种属性了
解析各种属性
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
是对Element所有元素进行解析
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) {
if (ele.hasAttribute("scope")) { //解析Scope属性
bd.setScope(ele.getAttribute("scope"));
} else if (containingBean != null) {
bd.setScope(containingBean.getScope());
}
if (ele.hasAttribute("abstract")) {//解析abstract属性
bd.setAbstract("true".equals(ele.getAttribute("abstract")));
}
String lazyInit = ele.getAttribute("lazy-init");
if ("default".equals(lazyInit)) { //解析lazy-init 属性
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit("true".equals(lazyInit));
String autowire = ele.getAttribute("autowire");//解析autowire属性
bd.setAutowireMode(this.getAutowireMode(autowire));
String dependencyCheck = ele.getAttribute("dependency-check")//解析dependency-check属性;
bd.setDependencyCheck(this.getDependencyCheck(dependencyCheck));
String autowireCandidate;
if (ele.hasAttribute("depends-on")) {//解析denpends-on属性
autowireCandidate = ele.getAttribute("depends-on");
bd.setDependsOn(StringUtils.tokenizeToStringArray(autowireCandidate, ",; "));
}
//解析autowire-candidate 属性
autowireCandidate = ele.getAttribute("autowire-candidate");
String destroyMethodName;
if (!"".equals(autowireCandidate) && !"default".equals(autowireCandidate)) {
bd.setAutowireCandidate("true".equals(autowireCandidate));
} else {
destroyMethodName = this.defaults.getAutowireCandidates();
if (destroyMethodName != null) {
String[] patterns = StringUtils.commaDelimitedListToStringArray(destroyMethodName);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
}
}
//解析primary 属性
if (ele.hasAttribute("primary")) {
bd.setPrimary("true".equals(ele.getAttribute("primary")));
}
//解析init-method 属性
if (ele.hasAttribute("init-method")) {
destroyMethodName = ele.getAttribute("init-method");
if (!"".equals(destroyMethodName)) {
bd.setInitMethodName(destroyMethodName);
}
} else if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
//解析destroy-method 属性
if (ele.hasAttribute("destroy-method")) {
destroyMethodName = ele.getAttribute("destroy-method");
if (!"".equals(destroyMethodName)) {
bd.setDestroyMethodName(destroyMethodName);
}
} else if (this.defaults.getDestroyMethod() != null) {
bd.setDestroyMethodName(this.defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
//解析factory-method属性
if (ele.hasAttribute("factory-method")) {
bd.setFactoryMethodName(ele.getAttribute("factory-method"));
}
//解析factory-bean属性
if (ele.hasAttribute("factory-bean")) {
bd.setFactoryBeanName(ele.getAttribute("factory-bean"));
}
return bd;
}
我们清楚的看见了 Spring对各个标签的解析 包括 我们经常用到的,不经常用的都进行了解析,解析来就让我们分析Spring 是如何 解析各个元素的。
image.png
解析Meta子标签
<bean id ="myTestMeta" class="com.zhh.MyTestMeta">
<meta key="testStr" value="testValue"/>
</bean>
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
NodeList nl = ele.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//判断当前节点是否是Meta
if (this.isCandidateElement(node) && this.nodeNameEquals(node, "meta")) {
Element metaElement = (Element)node;
String key = metaElement.getAttribute("key");
String value = metaElement.getAttribute("value");
//使用BeanMetadataAttribute 封装Meta 的Key和Value
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
attribute.setSource(this.extractSource(metaElement));
attributeAccessor.addMetadataAttribute(attribute);
}
}
}
解析子标签LookUp-method
或许LookUp-method 子标签并不常用 我们通过一个列子来说明
public Class User{
public void showme(){
System.out.println("I am User");
}
}
public Class Teacher Extends User{
public void showme(){
System.out.println("i am teaacher");
}
}
//创建调用方法
public abstract class GetBeanTest{
public void showme(){
this.getBean.showme();
}
public abstract User getBean();
}
//xml配置
<bean id="getBeanTest" class="com.zhh.GetBeanTest">
<lookup-method name="getBean" bean="teacher"/>
</bean>
<bean id="teacher" class="com.zhh.Teacher"/>
//运行结果
i an Teacher
抽象方法没有被实现 怎么会被调用呢 我们看配置 完成的功能是,动态的将teacher所代表的的bean 作为getBean的返回值 。我们看是如何解析的
public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//当且仅当 当前子标签lookup-method 是在进行解析
if (this.isCandidateElement(node) && this.nodeNameEquals(node, "lookup-method")) {
Element ele = (Element)node;
String methodName = ele.getAttribute("name");
String beanRef = ele.getAttribute("bean");
//使用lookupOverride 封装name和bean元素
LookupOverride override = new LookupOverride(methodName, beanRef);
override.setSource(this.extractSource(ele));
overrides.addOverride(override);
}
}
}
解析replaced-method 子标签
如果说 lookup-method 中的属性bean 所代表的的bean 作为属性name 的返回值。那么replaced-method 可以动态的改变 原有方法的逻辑
public class TestChangeMethod(){
public void changeMethod(){
Sytem.out.println("change me");
}
}
//如果有一天 在上线后 要改变原有的逻辑怎么办?
pulic class TestMethodReplacer implements org.springframework.beans.factory.support.MethodReplacer{
public Object reimplement(Object obj,Method method,Object []){
System.out.println("我替换了原来的方法.....");
return null;
}
}
//xml 这样配置
<bean id="testChangeMethod" class="test.replacemethod.TestChangeMethod">
<replaced-method name="changeMe" replace="replace">
</bean>
<bean id ="replace" class="com.zhh.TestMethodReplacer"/>
解析来我们看是如何解析的 replace-method标签的
public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//判断当前标签是否是replaced-method 字标签
if (this.isCandidateElement(node) && this.nodeNameEquals(node, "replaced-method")) {
Element replacedMethodEle = (Element)node;
//提取要替换旧的方法的名称
String name = replacedMethodEle.getAttribute("name");
//提取对应的新的替换方法
String callback = replacedMethodEle.getAttribute("replacer");
//创建用于封装name和replace 的实例bean ReplaceOverride
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, "arg-type");
Iterator var11 = argTypeEles.iterator();
while(var11.hasNext()) {
Element argTypeEle = (Element)var11.next();
String match = argTypeEle.getAttribute("match");
match = StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle);
if (StringUtils.hasText(match)) {
replaceOverride.addTypeIdentifier(match);
}
}
replaceOverride.setSource(this.extractSource(replacedMethodEle));
overrides.addOverride(replaceOverride);
}
}
}
解析子元素Conctructor-arg
Conctructor-age 字标签是非常常用的
<bean id ="helloBean" class="com.zhh.hellobean">
<conctructor-arg index="0">
<value>aaaa</value>
</conctructor-arg>
</bean>
以上是conctructor-arg最基本的用法 那么我们看是如何解析的?
public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
String indexAttr = ele.getAttribute("index");//获取index 属性
String typeAttr = ele.getAttribute("type");//获取type属性
String nameAttr = ele.getAttribute("name");//获取name属性
if (StringUtils.hasLength(indexAttr)) { //判断是否有index属性
try {
int index = Integer.parseInt(indexAttr);
if (index < 0) {
this.error("'index' cannot be lower than 0", ele);
} else {
try {
this.parseState.push(new ConstructorArgumentEntry(index));
Object value = this.parsePropertyValue(ele, bd, (String)null);
ValueHolder valueHolder = new ValueHolder(value);
if (StringUtils.hasLength(typeAttr)) {
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
valueHolder.setName(nameAttr);
}
valueHolder.setSource(this.extractSource(ele));
if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
this.error("Ambiguous constructor-arg entries for index " + index, ele);
} else {
bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
}
} finally {
this.parseState.pop();
}
}
} catch (NumberFormatException var19) {
this.error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
}
} else {
//没有index属性自动寻找
try {
this.parseState.push(new ConstructorArgumentEntry());
Object value = this.parsePropertyValue(ele, bd, (String)null);
ValueHolder valueHolder = new ValueHolder(value);
if (StringUtils.hasLength(typeAttr)) {
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
valueHolder.setName(nameAttr);
}
valueHolder.setSource(this.extractSource(ele));
bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
} finally {
this.parseState.pop();
}
}
}
1.判断是否有index属性 ,有 则步骤如下
1.1 解析constructor-arg的子元素
1.2 使用ConstructorArgmentValues.ValueHolder封装 解析出来的元素
1.3 将 封装的元素添加到BeanDefinition中的ContrucotrAgrmentValues的IndexedArgumentValue元素中
2.没有则步骤如下
1.1 解析constructor-arg的子元素
1.2 使用ConstructorArgmentValues.ValueHolder封装 解析出来的元素
1.3 将 封装的元素添加到BeanDefinition中的ContrucotrAgrmentValues的GenericArgumentValue元素中
没有Index和 有index 关键在于封装的位置不同 有Index属性封装在IndexedArgumentValue 没有封装在 GenericArgumentValue中
那么我们分析一下 parsePropertyValue()这个方法
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
String elementName = propertyName != null ? "<property> element for property '" + propertyName + "'" : "<constructor-arg> element";
NodeList nl = ele.getChildNodes();
Element subElement = null;
//一个属性只能对应一种类型
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
//对description和meta 不做处理
if (node instanceof Element && !this.nodeNameEquals(node, "description") && !this.nodeNameEquals(node, "meta")) {
if (subElement != null) {
this.error(elementName + " must not contain more than one sub-element", ele);
} else {
subElement = (Element)node;
}
}
}
//提取ref属性
boolean hasRefAttribute = ele.hasAttribute("ref");
boolean hasValueAttribute = ele.hasAttribute("value");//提取value属性
if (hasRefAttribute && hasValueAttribute || (hasRefAttribute || hasValueAttribute) && subElement != null) {
//Contructor-age上不存在
//既有ref属性又有value属性 存在ref又有子元素或者value属性又有子元素
this.error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
//对ref的处理 用RuntimeBeanReference 封装
if (hasRefAttribute) {
String refName = ele.getAttribute("ref");
if (!StringUtils.hasText(refName)) {
this.error(elementName + " contains empty 'ref' attribute", ele);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(this.extractSource(ele));
return ref;
} else if (hasValueAttribute) {//对value属性的处理 用 TypedStringValue封装
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute("value"));
valueHolder.setSource(this.extractSource(ele));
return valueHolder;
} else if (subElement != null) {//解析子元素
return this.parsePropertySubElement(subElement, bd);
} else {
this.error(elementName + " must specify a ref or value", ele);
return null;
}
}
上述步骤可以分为:
1.不提取description和meta
2.提取ref和value属性 同时判断不能同时存在ref属性和value属性
3.对ref属性进行提取 用RuntimeBeanReference封装
4.对value属性进行提取 用 TypedStringValue封装
5.对子元素进行解析
<constructor-arg>
<map>
<entry key="key" value="value"/>
</map>
</constructor-arg>
则对子元素进行提取,则解析过程如下
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
if (!this.isDefaultNamespace((Node)ele)) {
return this.parseNestedCustomElement(ele, bd);
} else if (this.nodeNameEquals(ele, "bean")) {
BeanDefinitionHolder nestedBd = this.parseBeanDefinitionElement(ele, bd);
if (nestedBd != null) {
nestedBd = this.decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
}
return nestedBd;
} else if (this.nodeNameEquals(ele, "ref")) {
String refName = ele.getAttribute("bean");
boolean toParent = false;
if (!StringUtils.hasLength(refName)) {
refName = ele.getAttribute("local");//解析local
if (!StringUtils.hasLength(refName)) {
refName = ele.getAttribute("parent"); //解析parent
toParent = true;
if (!StringUtils.hasLength(refName)) {
this.error("'bean', 'local' or 'parent' is required for <ref> element", ele);
return null;
}
}
}
if (!StringUtils.hasText(refName)) {
this.error("<ref> element contains empty target attribute", ele);
return null;
} else {
RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
ref.setSource(this.extractSource(ele));
return ref;
}
} else if (this.nodeNameEquals(ele, "idref")) {//对idref元素进行解析
return this.parseIdRefElement(ele);
} else if (this.nodeNameEquals(ele, "value")) {//对Value进行解析
return this.parseValueElement(ele, defaultValueType);
} else if (this.nodeNameEquals(ele, "null")) {//对null 进行解析
TypedStringValue nullHolder = new TypedStringValue((String)null);
nullHolder.setSource(this.extractSource(ele));
return nullHolder;
} else if (this.nodeNameEquals(ele, "array")) {//对array进行解析
return this.parseArrayElement(ele, bd);
} else if (this.nodeNameEquals(ele, "list")) {//对list进行解析
return this.parseListElement(ele, bd);
} else if (this.nodeNameEquals(ele, "set")) {/对set进行解析
return this.parseSetElement(ele, bd);
} else if (this.nodeNameEquals(ele, "map")) {//对map进行解析
return this.parseMapElement(ele, bd);
} else if (this.nodeNameEquals(ele, "props")) {//对props进行解析
return this.parsePropsElement(ele);
} else {
this.error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
}
解析子标签property
public void parsePropertyElement(Element ele, BeanDefinition bd) {
String propertyName = ele.getAttribute("name");//解析属性name的值
if (!StringUtils.hasLength(propertyName)) {
this.error("Tag 'property' must have a 'name' attribute", ele);
} else {
this.parseState.push(new PropertyEntry(propertyName));
try {
if (!bd.getPropertyValues().contains(propertyName)) {
Object val = this.parsePropertyValue(ele, bd, propertyName);
PropertyValue pv = new PropertyValue(propertyName, val);//将返回出来的值用PropertyValue 进行封装
this.parseMetaElements(ele, pv);
pv.setSource(this.extractSource(ele));
bd.getPropertyValues().addPropertyValue(pv);
return;
}
this.error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
} finally {
this.parseState.pop();
}
}
}
解析字标签Qualifier
对Qualifer 的使用如下
<bean id="myTest" class="com.zhh.MyTestBean">
<qualifier type="org.springframeWork.beans.annotaion.Qualifier" value="qf">
</bean>
具体解析如下
public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
String typeName = ele.getAttribute("type");//对type进行提取
if (!StringUtils.hasLength(typeName)) {
this.error("Tag 'qualifier' must have a 'type' attribute", ele);
} else {
this.parseState.push(new QualifierEntry(typeName));
try {
AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);//创建用于封装type 和 value的AutowireCandidateQualifier
qualifier.setSource(this.extractSource(ele));
String value = ele.getAttribute("value");
if (StringUtils.hasLength(value)) {
qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
}
NodeList nl = ele.getChildNodes();
for(int i = 0; i < nl.getLength(); ++i) {
Node node = nl.item(i);
if (this.isCandidateElement(node) && this.nodeNameEquals(node, "attribute")) {
Element attributeEle = (Element)node;
String attributeName = attributeEle.getAttribute("key");
String attributeValue = attributeEle.getAttribute("value");
if (!StringUtils.hasLength(attributeName) || !StringUtils.hasLength(attributeValue)) {
this.error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
return;
}
BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
attribute.setSource(this.extractSource(attributeEle));
qualifier.addMetadataAttribute(attribute);
}
}
bd.addQualifier(qualifier);
} finally {
this.parseState.pop();
}
}
}
到这里我们也分析了默认标签的解析与提取过程,当前我们分析了
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);这句话
那么我们接着分析 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
其实程序执行到这一步 Spring默认的标签以及执行完了 而这一步是对自定义标签进行解析
注册解析的BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
//使用beanName作为唯一标识
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());//通过BeanName注册
//获取所有的别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String aliase = var4[var6];
registry.registerAlias(beanName, aliase);//通过BeanName注册别名
}
}
}
从上面我们可以看出,解析的beanDefinition都会注册到BeanDefinitionRegistry类型的实例registry中
1.通过BeanName注册BeanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var7) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var7);
}
}
Map var3 = this.beanDefinitionMap;
//因为beanDefinitionMap是全局变量 会存在并发
synchronized(this.beanDefinitionMap) {
//根据beanName获取bean
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) { //如果根据beanName获取bean以及存在 并且判断是否可以覆盖,如果不运行覆盖 则抛出异常
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
}
if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + " with a framework-generated bean definition ': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else {
this.beanDefinitionNames.add(beanName);//记录beanName
this.frozenBeanDefinitionNames = null;
}
//注册BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
//重置BeanName对应的缓存
this.resetBeanDefinition(beanName);
}
1.根据beanName获取BeanDefintion 如果已近注册的情况下,并且设置了不允许Bean覆盖则,需要抛出异常
2.加入map缓存
3.清除之前留下的对应的BeanName的缓存
2.通过别名注册BeanDefinition
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
if (alias.equals(name)) {
this.aliasMap.remove(alias);
} else {
if (!this.allowAliasOverriding()) {//若alias不允许被覆盖,则抛出异常
String registeredName = (String)this.aliasMap.get(alias);
if (registeredName != null && !registeredName.equals(name)) {
throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'.");
}
}
this.checkForAliasCircle(name, alias);
this.aliasMap.put(alias, name);
}
}
3.通过监听器解析以及注册既注册完成
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));