spring源代码之标签的解析

内容接上一篇文章 Spring源代码之bean的基本解析,讲到了默认标签的解析,这里接上内容:

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            //获得beans节点的子节点
            NodeList nl = root.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                //如果子节点的element
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                        //bean的解析,默认标签
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        //bean的解析,自定义标签
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            delegate.parseCustomElement(root);
        }
    }

直说默认标签的解析parseDefaultElement(ele, delegate),进入方法:

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        //import标签的解析
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        //alias标签的解析
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        //bean标签解析
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }
        //beans标签的解析,如果是beans,会继续解析里面的标签(一般就是bean),那么还会回来到这个方法,这块其实是一个循环引用
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

先看bean标签的解析,其实,基本上所有的标签属性等都在BeanDefinitionParserDelegate这里声明了,看到这里会有一些激动,因为这是一个单独的类,终于没有继承,实现别的类活接口了!先看bean标签的解析,这块儿没有结构性的复杂,但是逻辑上跟复杂!

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //调用BeanDefinitionParserDelegate类的(ele)方法解析,这里会得到一些属性
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                // Register the final decorated instance.
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            // Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

delegate.parseBeanDefinitionElement(ele);进入这个方法里:

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        //获得标签的id属性
        String id = ele.getAttribute(ID_ATTRIBUTE);
        //获得标签name属性
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

        List<String> aliases = new ArrayList<>();
        //如果有name属性,分割name属性,以","或者";"
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            aliases.addAll(Arrays.asList(nameArr));
        }

        //声明beanName并把id赋值给他
        String beanName = id;
        //如果beanName为空,并且aliases不是空,上面nameArr分割的第一个值赋值给beanName,并且删除
        //如果beanName也就是ID为null其实这里不抛,后面也会跑异常的
        if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
            beanName = aliases.remove(0);
            if (logger.isDebugEnabled()) {
                logger.debug("No XML 'id' specified - using '" + beanName +
                        "' as bean name and " + aliases + " as aliases");
            }
        }

        //参数containingBean传过来的就是null
        if (containingBean == null) {
            //检查唯一性
            checkNameUniqueness(beanName, aliases, ele);
        }

        //上面代码是处理bean标签的id,name属性,到这个方法里,就是其他属性了,这里面也很多
        AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
        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);
                        // Register an alias for the plain bean class name, if still possible,
                        // if the generator returned the class name plus a suffix.
                        // This is expected for Spring 1.2/2.0 backwards compatibility.
                        String beanClassName = beanDefinition.getBeanClassName();
                        if (beanClassName != null &&
                                beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                                !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                            aliases.add(beanClassName);
                        }
                    }
                    if (logger.isDebugEnabled()) {
                        logger.debug("Neither XML 'id' nor 'name' specified - " +
                                "using generated bean name [" + beanName + "]");
                    }
                }
                catch (Exception ex) {
                    error(ex.getMessage(), ele);
                    return null;
                }
            }
            String[] aliasesArray = StringUtils.toStringArray(aliases);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }

        return null;
    }

上部分代码片里的parseBeanDefinitionElement(ele, beanName, containingBean);方法:

public AbstractBeanDefinition parseBeanDefinitionElement(
            Element ele, String beanName, BeanDefinition containingBean) {

        this.parseState.push(new BeanEntry(beanName));

        //获得class属性的内容
        String className = null;
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
        }

        //获得parent属性
        try {
            String parent = null;
            if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
                parent = ele.getAttribute(PARENT_ATTRIBUTE);
            }
            //创建AbstractBeanDefinition,这个类的用处是装这些属性,实际上是GenericBeanDefinition也就是他的子类
            //这个方法点进去会有bd.setBeanClass(ClassUtils.forName(className, classLoader))这样一行代码
            //这个代码就是用同意虚拟机下的类加载器,来生成bean的类
            AbstractBeanDefinition bd = createBeanDefinition(className, parent);
            //解析各种其他属性
            parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            //获得description,并放入创建AbstractBeanDefinition
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

            //获得元数据
            parseMetaElements(ele, bd);
            //获得lookup-method"
            parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            //获得replaced-method属性
            parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
            //获得构造函数
            parseConstructorArgElements(ele, bd);
            //获得property
            parsePropertyElements(ele, bd);
            //获得qualifier
            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;
    }

这块儿代码的核心就是返回一个AbstractBeanDefinition类型的数据,其实这个就是装在bean各种属性的一个容器.继续往里面看,他返回的是GenericBeanDefinition,他是AbstractBeanDefinition的子类.经过一层层的调用,我贴出的代码片,也就是processBeanDefinition方法里,会有一个BeanDefinitionHolder,就是这来的,只不过GenericBeanDefinition是放入BeanDefinitionHolder,又多了一层容器,那么逻辑关系也就是GenericBeanDefinition继承了AbstractBeanDefinition,而BeanDefinitionHolder才是他们的容器!
说到了BeanDefinition,上面只提到了GenericBeanDefinition,其实还有另外两种BeanDefinition,他们都实现了BeanDefinition接口并继承了AbstractBeanDefinition.
下面层级的代码,不想往这贴了,太多了,但是我都加了注释,或者正在家注释,这是一个工作量很大的事儿,没有太多的技术含量,需要的只是一点点看,所以想看的话可以去spring源代码中文注释这里看!

写到这里,其实可以顺着这个思路来细看了,脉络已经出来了,其实这里面很关键的就是AbstractBeanDefinition,说白了,bean的解析过程,无非就是将xml内容,转移到这个类中,那么梳理一下这个类的各种属性:

//删除了常亮等
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
        implements BeanDefinition, Cloneable {

    //classLoader生成的bean实例
    private volatile Object beanClass;

    //bean的作用范围
    private String scope = SCOPE_DEFAULT;

    //是否是抽象
    private boolean abstractFlag = false;

    //是否懒加载
    private boolean lazyInit = false;

    //自动注入模式,对应bean的属性autowire
    private int autowireMode = AUTOWIRE_NO;
    //依赖检查
    private int dependencyCheck = DEPENDENCY_CHECK_NONE;
    //一个bean实例化,依赖的别的bean
    private String[] dependsOn;
    //查找自动装配对象
    private boolean autowireCandidate = true;
    //自动装备时候,多个bean是否是首选
    private boolean primary = false;
    //记录qualifier
    private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(0);
    //这个有待研究
    private Supplier<?> instanceSupplier;
    //允许访问飞公开的构造器
    private boolean nonPublicAccessAllowed = true;
    //宽松模式解析构造器
    private boolean lenientConstructorResolution = true;
    //属性factory-bean
    private String factoryBeanName;
    //属性factory-method
    private String factoryMethodName;
    //构造器值
    private ConstructorArgumentValues constructorArgumentValues;
    //属性集合
    private MutablePropertyValues propertyValues;
    //方法重写的持有者
    private MethodOverrides methodOverrides = new MethodOverrides();
    //属性init-method
    private String initMethodName;
    //destroy-method
    private String destroyMethodName;
    //是否执行initMethodName
    private boolean enforceInitMethod = true;
    //是否执行destroy-method
    private boolean enforceDestroyMethod = true;
    //创建aop时候为true
    private boolean synthetic = false;

    private int role = BeanDefinition.ROLE_APPLICATION;
    //描述信息
    private String description;
    //bean定义的资源
    private Resource resource;

说到这里,挖掘出这个抽象类,其实解析这里已经差不多了,至于其他的详细解析,太多了,没法往这上面贴,还有就是自定义标签没打算说,还有就是开始数第三个代码片中的bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);这个也没打算说,这个是默认标签下的自定义属性(标签)解析,所以也不说了,不知道的可以去查一下怎么去自定义属性(标签),下一篇文章会是bean的加载!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值