Springy源码笔记(二)默认标签解析

上一回讲到对XML配置文件的解析,class DefaultBeanDefinitionDocumentReader类接下来对具体的标签进行更进一步的解析:

if (delegate.isDefaultNamespace(ele)) {
    parseDefaultElement(ele, delegate);//默认标签
}
else {
    delegate.parseCustomElement(ele);//自定义标签
}
  1. parseDefaultElement(ele, delegate)

    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
    // recurse
    doRegisterBeanDefinitions(ele);
    }

    这里分别对应着import,alias,bean,beans标签的解析;这里我们解析processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)这个方法;

  2. processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)

    对Bean进行解析

  3. delegate.parseBeanDefinitionElement(ele)

    BeanDefinitionParserDelegate类,有状态的委托类,用于解析XML bean定义。 该方法调用内部重载的方法: parseBeanDefinitionElement(ele, null);

  4. parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)

    Element :即包含XML标签的属性;

    BeanDefinition :描述了一个bean实例,该实例具有属性值,构造函数参数值以及具体实现所提供的更多信息。它是一个接口,继承AttributeAccessor, BeanMetadataElement。

    String id = ele.getAttribute(ID_ATTRIBUTE);
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    List<String> aliases = new ArrayList<String>();
    if (StringUtils.hasLength(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr,      MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }
    String beanName = id;
    ......
    beanName = this.readerContext.generateBeanName(beanDefinition);

    获取Bean的id标签值,并将id赋值给beanName,即代表Bean的id;

    获取Bean的name属性。因为name属性有多个,对name字符串进行分割,使用List进行存储,

    后续对beanName进行检查,是否唯一;

    如果beanName不存在,则生成一个新的beanName;

  5. parseBeanDefinitionElement(ele, beanName, containingBean)

    进一步解析标签,同时该方法的返回值类型为AbstractBeanDefinition;

    AbstractBeanDefinition:抽象类,继承BeanMetadataAttributeAccessor实现BeanDefinition, Cloneable 接口。是BeanDefinition的实现以及扩充;BeanMetadataAttributeAccessor,则代表的是一些元数据属性;

            String className = null;
    ......
            String parent = null;
    ......
    ---------------------------------------------------------------------------------
                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);

    在该方法内解析bean标签的属性有 :class,parent这两个主要属性,

    其他属性由parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);该方法解析:解析的属性有:scope,primary,lazy-init,init-method,autowire,abstract,depends-on,factory-bean,等等;

    同时Bean的子标签则使用具体的解析方法进行解析,解析的Bean的子标签有:

    <meta key="" value=""/>  --》parseMetaElements(ele, bd);
    <lookup-method></lookup-method> --》 parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
    <replaced-method></replaced-method> --》 parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
    <property name=""></property> --》  parsePropertyElements(ele, bd);
    <constructor-arg></constructor-arg>  --》 parseConstructorArgElements(ele, bd);
    <qualifier></qualifier> --》parseQualifierElements(ele, bd);

     

  6. AbstractBeanDefinition bd = createBeanDefinition(className, parent);

在上面的代码中,可以看到对子节点的解析都用到AbstractBeanDefinition实例, createBeanDefinition(className, parent);方法即返回一个AbstractBeanDefinition实例,进入createBeanDefinition方法,方法体为:

return BeanDefinitionReaderUtils.createBeanDefinition(
    parentName, className, this.readerContext.getBeanClassLoader());

进入该方法,我们会发现他调用BeanDefinitionReaderUtils.createBeanDefinition方法,继续进入:

GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
......
return bd;

返现bd对象,就是GenericBeanDefinition的实例;

GenericBeanDefinition

GenericBeanDefinition 继承AbstractBeanDefinition。BeanDefinition是一个接口,是配置文件在类中的映射,每一个标签都有对应的属性,它有三个子类,RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition.如果Bean有父Bean,则父Bean使用RootBeanDefinition,如果有子Bean,则使用ChildBeanDefinition.GenericBeanDefinition则是对一般Bean的配置映射。

以:parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);为例:

if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
        error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
}
        else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
            bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
}
        else if (containingBean != null) {
            // Take default from containing bean in case of an inner bean definition.

使用eles实例来判断XML文件中是否设置了某个属性,如果有,则使用bd对象的set方法进行配置文件到内部存储的映射;

当该方法的所有标签都解析完毕后,则代表的系统默认的标签的解析已经完毕,即eanDefinitionHolder delegate.parseBeanDefinitionElement(ele);方法执行完毕,并返回BeanDefinitionHolder实例;接下来的处理就是对默认标签中的自定义标签元素以及注册的处理;

BeanDefinitionHolder

具有名称和别名的BeanDefinition的持有人。可以理解为BeanDefinition的代表;

7.delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

判断是否需要对BeanDefinition进行装饰,当有自定义标签时,则进行装饰;该方法调用内部的重载方法;

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
            Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
        ......
NamedNodeMap attributes = ele.getAttributes();
        for (int i = 0; i < attributes.getLength(); i++) {
            Node node = attributes.item(i);
            finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
        }
        ......
}

获取所有属性,并判断属性是否需要进行装饰;

    public BeanDefinitionHolder decorateIfRequired(
            Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
            ......
            if (!isDefaultNamespace(namespaceUri)) {
            NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
            if (handler != null) {
                return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
            }
            else if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) {
                error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
            }
            ......
            }
    }   

判断是否是默认的命名空间,如果不是,则找到对应的命名空间解析器进行处理,如果是默认的标签,则略;

8. 注册BeanDefinition

public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
......
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
......
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
......
        }
    }
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName,   definitionHolder.getBeanDefinition());
for (String alias : aliases) {
        registry.registerAlias(beanName, alias);
}

使用beanName作为注册的标识,对Bean进行注册,同时注册所有别名;

registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
        Assert.hasText(beanName, "'beanName' must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }

进行beanName的判断,然后简单的将bean放入到一个Map对象中;由于并发的安全的问题,这里使用ConcurrentHashMap创建对象;

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

注册别名同理;

9.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));

完成解析,但是最后为了扩展可以对注册的BeanDefinition事件进行监听时,可以注册监听器将处理逻辑写入到监听器中。

public void fireComponentRegistered(ComponentDefinition componentDefinition) {
        this.eventListener.componentRegistered(componentDefinition);
    }
public interface ReaderEventListener extends EventListener {
......
    void componentRegistered(ComponentDefinition componentDefinition);
......
}
​

 

参考《Spring源码深度解析》, 如有问题,敬请指出,与君共勉

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值