Spring 源码

Spring 源码分析之默认标签解析

2019-03-17  本文已影响36人  以南之南_b9a1

上一节 我们说到 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));
上一篇下一篇

猜你喜欢

热点阅读