zoukankan      html  css  js  c++  java
  • loadBeanDefinitions方法源码跟踪(二)

    因为字数超过了限制,所以分成了三篇,承接上篇:
    https://www.jianshu.com/p/a0cfaedf3fc5

    代码过宽,可以shift + 鼠标滚轮 左右滑动查看

    3.parseDefaultElement

    先跟踪一个bean标签,下面是对应的配置文件

    <!--配置mapper.java扫描-->
    <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="cn.mrdear.mapper"/>
        <property name="properties">
            <value>
                mappers=tk.mybatis.mapper.common.Mapper
            </value>
        </property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
    

    因为是bean标签,走的默认的名称空间方法,所以走这个标签的方法:

    //3.如果该标签属于beans的名称空间,则进入这个方法
    //xmlns="http://www.springframework.org/schema/beans"
    parseDefaultElement(ele, delegate);
    

    这个方法的实现在DefaultBeanDefinitionDocumentReader类中,因为标签下有多个子标签,所以每个子标签对应着一个方法

    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>标签进入这个方法
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            
            // recurse
            // 如果是嵌套的beans,那么就会重新调用标记2中的一个方法进行递归
            doRegisterBeanDefinitions(ele);
        }
    }
    
    
    /**
    * Process the given bean element, parsing the bean definition
    * and registering it with the registry.
    *
    * 处理bean元素,解析成bean definition并注册到工厂中
    */
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
       
        //3.1通过代理解析bean元素
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            
            //3.2如果有要求的话渲染beanDefinition
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                
                // Register the final decorated instance.
                //3.3注册最终被渲染的实例到工厂中
                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));
        }
    }
    

    3.1 parseBeanDefinitionElement

    跟踪3.1标记的方法

    进入BeanDefinitionParserDelegate类的parseBeanDefinitionElement方法

    //3.1通过代理解析bean元素
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    
    
    /**
    * Parses the supplied {@code <bean>} element. May return {@code null}
    * if there were errors during parse. Errors are reported to the
    * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
    * 
    * 解析bean元素。如果解析过程中发生错误则返回空
    */
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
        return parseBeanDefinitionElement(ele, null);
    }
    
    
    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        
        //拿bean标签上的id
        String id = ele.getAttribute(ID_ATTRIBUTE);
        
        //拿bean标签上的name属性
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    
        List<String> aliases = new ArrayList<String>();
        
        //有name属性进入
        if (StringUtils.hasLength(nameAttr)) {
            
            //name属性对应的name值如果有分隔符",; ",那么切分成数组
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            
            //这些name值就是别名
            aliases.addAll(Arrays.asList(nameArr));
        }
    	
        //指定了id就用id值作为bean名称
        String beanName = id;
        
        //如果没有id,但是指定了name,就用name值作为bean名称
        if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
            
            //拿第一个name值作为bean名称,其余的还是别名
            beanName = aliases.remove(0);
            if (logger.isDebugEnabled()) {
                logger.debug("No XML 'id' specified - using '" + beanName +
                             "' as bean name and " + aliases + " as aliases");
            }
        }
    
        if (containingBean == null) {
            
            //检查bean名称和别名是否已经被使用了,如果用了就报错
            //同时把这个bean的名称和别名加入代理的usedNames属性中
            //private final Set<String> usedNames = new HashSet<String>();
            checkNameUniqueness(beanName, aliases, ele);
        }
    	
        //直接进入这个方法
        AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
            
            //既没有指定id,也没有指定name就走这里面
            if (!StringUtils.hasText(beanName)) {
                try {
                    
                    //前面containingBean传递时为null,这里不走这个方法
                    if (containingBean != null) {
                        beanName = BeanDefinitionReaderUtils.generateBeanName(
                            beanDefinition, this.readerContext.getRegistry(), true);
                    }
                    else {
                        
                        //生成一个bean名称,beanName
                        //如果这个bean是内部bean,全限定名后加#号再加哈希值
                        //如果是顶层bean,那么后面加#号再从0开始加数字,id已被注册数字就增1,直到唯一
                        //比如:tk.mybatis.spring.mapper.MapperScannerConfigurer#0
                        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)) {
                            
                            //如果该类名没有被使用,那么注册该类名作为别名,比如:
                            //tk.mybatis.spring.mapper.MapperScannerConfigurer作为
                            //tk.mybatis.spring.mapper.MapperScannerConfigurer#0的别名
                            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);
            
            //返回beanDefinition的持有者
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }
    
        return null;
    }
    
    
    
    /**
    * Parse the bean definition itself, without regard to name or aliases. May return
    * {@code null} if problems occurred during the parsing of the bean definition.
    * 
    * 不关注名称和别名,只解析bean definition自身
    */
    public AbstractBeanDefinition parseBeanDefinitionElement(
        Element ele, String beanName, BeanDefinition containingBean) {
        
    	//解析的时候放入,解析完成弹出,这里放入bean标签,
        //如果还嵌套有子标签,则后续放入子标签
        //子标签先弹出
        this.parseState.push(new BeanEntry(beanName));
    
        String className = null;
        if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
            
            //如果有指定class属性,则拿到class属性值
            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
        }
    
        try {
            String parent = null;
            if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
                
                //如果有指定parent属性,则拿到parent属性值
                parent = ele.getAttribute(PARENT_ATTRIBUTE);
            }
            
            //3.1.1创建BeanDefinition并设置两属性
            AbstractBeanDefinition bd = createBeanDefinition(className, parent);
            
    	    //3.1.2将bean标签上的属性设置到bean definition中
            parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            
            //如果bean标签下有子标签为description,拿到标签中的文本,设置到bean definition中
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
            
    	    //如果bean标签下有子标签为meta,拿到他的key和value属性,设置到bean definition中
            parseMetaElements(ele, bd);
            
            //如果bean标签下有子标签为lookup-method,拿到他的name和bean属性,设置到bean definition中
            parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            
            //如果bean标签下有子标签为replaced-method,设置bean definition 
            parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
            
    	    //如果bean标签下有子标签为constructor-arg,设置bean definition的构造方式
            parseConstructorArgElements(ele, bd);
            
            //这个标签比较常用,为Property标签
            //3.1.3解析Property的属性设置到bean definition中
            parsePropertyElements(ele, bd);
            
            //有qualifier子标签才走这个方法
            parseQualifierElements(ele, bd);
            
    	    //设置资源
            bd.setResource(this.readerContext.getResource());
            
            //这里为null
            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;
    }
    

    3.1.1 createBeanDefinition

    跟踪标记3.1.1

    //3.1.1创建BeanDefinition并设置两属性
    AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    
    /**
    * Create a bean definition for the given class name and parent name.
    *
    * 通过给定的className和parentName创建beanDefinition
    */
    protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
        throws ClassNotFoundException {
    
        return BeanDefinitionReaderUtils.createBeanDefinition(
            parentName, className, this.readerContext.getBeanClassLoader());
    }
    
    /**
    * 此方法是BeanDefinitionReaderUtils的静态方法
    *
    * Create a new GenericBeanDefinition for the given parent name and class name,
    * eagerly loading the bean class if a ClassLoader has been specified.
    *
    * 通过给定的parentName和className穿件一个新的GenericBeanDefinition
    * 如果指定了ClassLoader,就提前加载bean class
    */
    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) {
                
                //接受的属性是Object类型
                bd.setBeanClass(ClassUtils.forName(className, classLoader));
            }
            else {
                
                //接受的属性是Object类型
                bd.setBeanClassName(className);
            }
        }
        return bd;
    }
    

    3.1.2 parseBeanDefinitionAttributes

    跟踪标记方法3.1.2

    此方法在BeanDefinitionParserDelegate类中

    //3.1.2将bean标签上的属性设置到bean definition中
    parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
    
    /**
    * Apply the attributes of the given bean element to the given bean * definition.
    *
    * 将bean标签上的属性设置到bean definition中
    */
    public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
                                                                BeanDefinition containingBean, AbstractBeanDefinition bd) {
        
    	//bean标签上已经没有singleton属性了,用scope代替,所以出现就报错
        if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
            error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
        }
        
        //如果设置了scope就拿其值
        else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
            bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
        }
        
        //此处containingBean为空
        else if (containingBean != null) {
            
            // Take default from containing bean in case of an inner bean definition.
            // 如果是一个内部的bean definition,用包含的bean的default
            bd.setScope(containingBean.getScope());
        }
        
    	//是否有abstract属性
        if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
            bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
        }
    
        String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
        
        //lazyInit如果没有设置则为默认值,默认值用的代理类中defaults属性,
        //也就是this.defaults
        if (DEFAULT_VALUE.equals(lazyInit)) {
            lazyInit = this.defaults.getLazyInit();
        }
        
        bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
        
    	//默认值用的代理类中defaults属性,不进行autowire
        String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
        bd.setAutowireMode(getAutowireMode(autowire));
        
    	//默认不进行依赖检查
        String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
        bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
        
    	//是否有depends-on属性
        if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
            String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
            bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
        }
        
    	//是否有autowire-candidate属性,没有或者为默认则不设置
        String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
        if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
            String candidatePattern = this.defaults.getAutowireCandidates();
            if (candidatePattern != null) {
                String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
                bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
            }
        }
        else {
            bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
        }
        
    	//是否有primary属性
        if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
            bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
        }
        
    	//是否有init-method属性
        if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
            String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
            if (!"".equals(initMethodName)) {
                bd.setInitMethodName(initMethodName);
            }
        }
        else {
            
            //没有init-method属性,就拿代理类defaults属性的
            if (this.defaults.getInitMethod() != null) {
                bd.setInitMethodName(this.defaults.getInitMethod());
                bd.setEnforceInitMethod(false);
            }
        }
        
    	//是否有destroy-method属性
        if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
            String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
            bd.setDestroyMethodName(destroyMethodName);
        }
        else {
            
            //没有destroy-method属性,就拿代理类defaults属性的
            if (this.defaults.getDestroyMethod() != null) {
                bd.setDestroyMethodName(this.defaults.getDestroyMethod());
                bd.setEnforceDestroyMethod(false);
            }
        }
        
    	//是否有factory-method属性
        if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
            bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
        }
        
        //是否有factory-bean属性
        if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
            bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
        }
    
        return bd;
    }
    

    这样,bean标签上的属性也就解析完成了,对其属性的描述不管设置了还是没有设置的,都有相应的值对应到bean definition中。接下来就要解析,bean标签下的子标签了。

    3.1.3 parsePropertyElements

    跟踪3.1.3标记的方法

    此方法在BeanDefinitionParserDelegate类中实现

    //3.1.3解析Property的属性设置到bean definition中
    parsePropertyElements(ele, bd);
    
    
    /**
    * Parse property sub-elements of the given bean element.
    * 解析bean标签下property子标签
    */
    public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
        NodeList nl = beanEle.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
                
                //标签名为property才能进入,进入这个方法
                parsePropertyElement((Element) node, bd);
            }
        }
    }
    
    
    /**
    * Parse a property element.
    */
    public void parsePropertyElement(Element ele, BeanDefinition bd) {
        
        //拿到property标签的name属性
        String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
        if (!StringUtils.hasLength(propertyName)) {
            error("Tag 'property' must have a 'name' attribute", ele);
            return;
        }
        
        //解析的时候放入,解析完成弹出,这里放入property标签,
        //这里面还存有bean父标签,子标签解析完成后先弹出
        this.parseState.push(new PropertyEntry(propertyName));
        try {
            
            //bean标签下可以有多个property,但是不能重复name属性
            if (bd.getPropertyValues().contains(propertyName)) {
                error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
                return;
            }
            
            //进入这个方法,查看是怎么解析property标签属性的
            Object val = parsePropertyValue(ele, bd, propertyName);
            
            //将name属性和对应的value放入
            PropertyValue pv = new PropertyValue(propertyName, val);
            
            //解析property标签的子标签meta,
            //拿到meta的key和value属性,设置到PropertyValue中
            parseMetaElements(ele, pv);
            
            //这里没有实现,为null
            pv.setSource(extractSource(ele));
            
            //将PropertyValue添加到bean definition中
            bd.getPropertyValues().addPropertyValue(pv);
        }
        finally {
            
            //解析的时候放入,解析完成弹出,这里放入property标签
            this.parseState.pop();
        }
    }
    
    
    
    
    /**
    * Get the value of a property element. May be a list etc.
    * Also used for constructor arguments, "propertyName" being null in this case.
    *
    * 拿到property标签的value值,可能是list
    * 也被constructor标签使用,这种情况propertyName为null
    */
    public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
       
        //如果propertyName为null,则是constructor-arg标签
        //否则为property标签
        String elementName = (propertyName != null) ?
            "<property> element for property '" + propertyName + "'" :
        "<constructor-arg> element";
    
        
        // Should only have one child element: ref, value, list, etc.
        //不管是哪种标签,下面都应该只有一个子标签: ref, value, list等.
        NodeList nl = ele.getChildNodes();
        Element subElement = null;
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
                !nodeNameEquals(node, META_ELEMENT)) {
                
                // Child element is what we're looking for.
                //除开description和meta标签,子标签最多只能有一个
                if (subElement != null) {
                    error(elementName + " must not contain more than one sub-element", ele);
                }
                else {
                    subElement = (Element) node;
                }
            }
        }
        
    	//看标签属性用的是value还是ref
        boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
        boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
        
        //value和ref属性不能同时存在,如果有子标签,则value和ref都不能存在,否则报错
        if ((hasRefAttribute && hasValueAttribute) ||
            ((hasRefAttribute || hasValueAttribute) && subElement != null)) {
            error(elementName +
                  " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
        }
        
    	//用的ref的情况
        if (hasRefAttribute) {
            String refName = ele.getAttribute(REF_ATTRIBUTE);
            if (!StringUtils.hasText(refName)) {
                error(elementName + " contains empty 'ref' attribute", ele);
            }
            RuntimeBeanReference ref = new RuntimeBeanReference(refName);
            ref.setSource(extractSource(ele));
            return ref;
        }
        
        //用的value的情况
        else if (hasValueAttribute) {
            TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
            valueHolder.setSource(extractSource(ele));
            return valueHolder;
        }
        
        //子标签不为null的情况,进入这个方法查看
        else if (subElement != null) {
            return parsePropertySubElement(subElement, bd);
        }
        else {
            
            // Neither child element nor "ref" or "value" attribute found.
            //没指定ref或者value或者子标签,返回null
            error(elementName + " must specify a ref or value", ele);
            return null;
        }
    }
    
    
    /**
    * 这个方法还是在BeanDefinitionParserDelegate中
    */
    public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
        return parsePropertySubElement(ele, bd, null);
    }
    
    /**
    * Parse a value, ref or collection sub-element of a property or
    * constructor-arg element.
    *
    * 解析property或者constructor-arg标签的子标签,可能为value, ref或者集合
    */
    public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
       
        //如果这个子标签不属于beans的名称空间,则走这个方法
        if (!isDefaultNamespace(ele)) {
            return parseNestedCustomElement(ele, bd);
        }
        
        //如果是bean子标签,则走这个方法
        else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
            BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
            if (nestedBd != null) {
                nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
            }
            return nestedBd;
        }
        
        //如果是ref子标签,则走这个方法
        else if (nodeNameEquals(ele, REF_ELEMENT)) {
            
            // A generic reference to any name of any bean.
            String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
            boolean toParent = false;
            if (!StringUtils.hasLength(refName)) {
                
                // A reference to the id of another bean in the same XML file.
                refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
                if (!StringUtils.hasLength(refName)) {
                    
                    // A reference to the id of another bean in a parent context.
                    refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
                    toParent = true;
                    if (!StringUtils.hasLength(refName)) {
                        error("'bean', 'local' or 'parent' is required for <ref> element", ele);
                        return null;
                    }
                }
            }
            if (!StringUtils.hasText(refName)) {
                error("<ref> element contains empty target attribute", ele);
                return null;
            }
            RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
            ref.setSource(extractSource(ele));
            return ref;
        }
        
        //如果是idref子标签,则走这个方法
        else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
            return parseIdRefElement(ele);
        }
        
        //如果是value子标签,则走这个方法
        else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
            
            //以这个方法作为演示,其他的方法都是大同小异,进入。
            return parseValueElement(ele, defaultValueType);
        }
        
        //如果是null子标签,则走这个方法
        else if (nodeNameEquals(ele, NULL_ELEMENT)) {
            
            // It's a distinguished null value. Let's wrap it in a TypedStringValue
            // object in order to preserve the source location.
            TypedStringValue nullHolder = new TypedStringValue(null);
            nullHolder.setSource(extractSource(ele));
            return nullHolder;
        }
        
        //如果是array子标签,则走这个方法
        else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
            return parseArrayElement(ele, bd);
        }
        
        //如果是list子标签,则走这个方法
        else if (nodeNameEquals(ele, LIST_ELEMENT)) {
            return parseListElement(ele, bd);
        }
        
        //如果是set子标签,则走这个方法
        else if (nodeNameEquals(ele, SET_ELEMENT)) {
            return parseSetElement(ele, bd);
        }
        
        //如果是map子标签,则走这个方法
        else if (nodeNameEquals(ele, MAP_ELEMENT)) {
            return parseMapElement(ele, bd);
        }
        
        //如果是props子标签,则走这个方法
        else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
            return parsePropsElement(ele);
        }
        
        //否则返回null,报错
        else {
            error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
            return null;
        }
    }
    
    
    /**
    * Return a typed String value Object for the given value element.
    *
    * 通过指定的value标签,返回指定的字符串value对象
    */
    public Object parseValueElement(Element ele, String defaultTypeName) {
        
        // It's a literal value.
        //拿到value中的文本,包括回车、tab制表符、空格
        String value = DomUtils.getTextValue(ele);
        
        //有无type属性
        String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);
        String typeName = specifiedTypeName;
        if (!StringUtils.hasText(typeName)) {
            
            //没有就用入参defaultTypeName
            typeName = defaultTypeName;
        }
        try {
            TypedStringValue typedValue = buildTypedStringValue(value, typeName);
            
            //这里设置为空
            typedValue.setSource(extractSource(ele));
            
            //这里为空字符串
            typedValue.setSpecifiedTypeName(specifiedTypeName);
            
            //返回typedValue
            return typedValue;
        }
        catch (ClassNotFoundException ex) {
            error("Type class [" + typeName + "] not found for <value> element", ele, ex);
            return value;
        }
    }
    

    3.2 decorateBeanDefinitionIfRequired

    在生成了BeanDefinitionHolder以后,如果需要的话应该通过代理类对bean definition进行渲染。

    跟踪标记3.2的方法

    该方法的实现在BeanDefinitionParserDelegate类中

    //3.2如果有要求的话渲染beanDefinition
    bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
    
    
    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
        return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
    }
    
    
    public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
        Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
    
        BeanDefinitionHolder finalDefinition = definitionHolder;
    
        // Decorate based on custom attributes first.
        // 首先基于自定义属性进行渲染
        // 也就是bean标签上的属性,也就是node
        // 只有当这个node不属于名称空间beans才会进行渲染,这里就不进去看了
        NamedNodeMap attributes = ele.getAttributes();
        for (int i = 0; i < attributes.getLength(); i++) {
            Node node = attributes.item(i);
            finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
        }
    
        // Decorate based on custom nested elements.
        // 然后根据标签内嵌套的子标签进行渲染
        // 这里是不属于名称空间beans的子标签才会进行渲染
        NodeList children = ele.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node node = children.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
            }
        }
        return finalDefinition;
    }
    

    3.3 registerBeanDefinition

    最终将完成的bean definition注册到工厂中

    跟踪标记3.3的方法

    //3.3注册最终被渲染的实例到工厂中
    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
    
    /**
    * Register the given bean definition with the given bean factory.
    *
    * 注册bean definition
    */
    public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {
    
        // Register bean definition under primary name.
        
        // 3.3.1注册bean definition的beanName
        // 比如tk.mybatis.spring.mapper.MapperScannerConfigurer#0
        String beanName = definitionHolder.getBeanName();
        
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
        // Register aliases for bean name, if any.
        
        // 如果有别名的话,为bean name注册别名
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                
                //3.3.2注册别名
                registry.registerAlias(beanName, alias);
            }
        }
    }
    

    3.3.1 registerBeanDefinition

    跟踪标记3.3.1的方法

    // 3.3.1注册bean definition的beanName
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    
    @Override
    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 {
                
                //做一个验证,静态工厂方法和覆盖方法不能组合使用
                //如果bean definition中的beanClass属性不是String类型而是Class类型
                //那么就要验证和准备这个bean定义的覆盖方法,检查指定名称的方法是否存在
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                                       "Validation of bean definition failed", ex);
            }
        }
    
        BeanDefinition oldBeanDefinition;
        
    	//查看beanName是否已经被注册在工厂的beanDefinitionMap属性中
        oldBeanDefinition = this.beanDefinitionMap.get(beanName);
        
        //已经被注册走这个方法,这里不查看
        if (oldBeanDefinition != null) {
            if (!isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                                       "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
                                                       "': There is already [" + oldBeanDefinition + "] bound.");
            }
            else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
                
                // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                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 (!beanDefinition.equals(oldBeanDefinition)) {
                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding bean definition for bean '" + beanName +
                                     "' with a different definition: replacing [" + oldBeanDefinition +
                                     "] with [" + beanDefinition + "]");
                }
            }
            else {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Overriding bean definition for bean '" + beanName +
                                      "' with an equivalent definition: replacing [" + oldBeanDefinition +
                                      "] with [" + beanDefinition + "]");
                }
            }
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            
            //这里面代表beanName还没有被注册
            //然后根据阶段不同又有一层判断
            if (hasBeanCreationStarted()) {
                
                //这个阶段是bean已经开始创建
                // Cannot modify startup-time collection elements anymore (for stable iteration)
                synchronized (this.beanDefinitionMap) {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            else {
                
                // Still in startup registration phase
                
                // 仍然处于启动时的注册阶段
                // 所以这里走这个方法
                //beanDefinitionMap是工厂的一个属性,ConcurrentHashMap类型
                //他保存所有解析好的bean Definition的名称和实例的映射
                this.beanDefinitionMap.put(beanName, beanDefinition);
                
                //beanName也单独使用了一个ArrayList来保存,方便遍历
                this.beanDefinitionNames.add(beanName);
                
                //如果该bean definition是手动注册的,还要从manualSingletonNames中
                //移除bean definition的beanName,还要从manualSingletonNames中是LinkedHashSet
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }
        
    	//这里跳过
        if (oldBeanDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
    }
    

    3.3.2 registerAlias

    跟踪3.3.2方法

    //3.3.2注册别名
    registry.registerAlias(beanName, alias);
    
    @Override
    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)) {
            
            //移除别名中的beanName
            //aliasMap是ConcurrentHashMap类型,保存别名和beanName的映射
            this.aliasMap.remove(alias);
        }
        else {
            String registeredName = this.aliasMap.get(alias);
            
            //如果别名对应beanName已经被注册,则不需要再注册一次
            //别名不允许被覆盖
            if (registeredName != null) {
                if (registeredName.equals(name)) {
                    
                    // An existing alias - no need to re-register
                    return;
                }
                if (!allowAliasOverriding()) {
                    throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                                                    name + "': It is already registered for name '" + registeredName + "'.");
                }
            }
            
            //再检查一遍,aliasMap中不能已经存在name和alias
            checkForAliasCircle(name, alias);
            
            //工厂的aliasMap属性保存别名,那么alias已被注册
            this.aliasMap.put(alias, name);
        }
    }
    

    这样,spring配置文件中为bean标签的解析和加载,也就跟踪完了。

    然后再看下非默认名称空间的标签的解析和加载。

    因为字数超过了限制,所以分成了三篇,点击下篇继续阅读
    https://www.jianshu.com/p/6e0f6fd1cbbd

    总结

    3

    • 走解析默认元素的方法。根据beans名称空间下,不同的标签有不同的子方法,对于<bean>标签来说,主要分为三步:
      • 3.1 通过代理 delegate 解析 bean 元素生成 BeanDefinitionHolder
      • 如果有必要的话,利用非默认名称空间的属性和子标签,渲染 BeanDefinitionHolder 中的 BeanDefinition
      • 注册最终被渲染的实例到工厂中。分两步,一步注册 BeanDefinition ,其实就是将 beanName 和 BeanDefinition 放入 beanDefinitionMap 中,beanName 放入 beanDefinitionNames中;一步注册别名,将 alias、name放入到 aliasMap 中

    ——————————————————————————————————

    • 3.1
    • 获取元素上的 id、name 属性,id 作为 beanName,name 作为别名。如果没有指定 id,取 name 的一个值作为 beanName,别名中移除该值。
    • 解析元素生成 BeanDefinition
    • 如果属性没有指定 id 也没有指定 name,利用 beanDefinition 生成一个 beanName。当这个bean是内部bean,类的全限定名加#号再加哈希值;当是顶层bean,类的全限定名加#号再从0开始加数字,id已被注册数字就增1,直到唯一。有了 beanName,再以类的全限定名作为别名。
    • 利用 BeanDefinition ,beanName ,别名,生成 BeanDefinitionHolder 并返回

    ——————————————————————————————————

    • 解析元素生成 BeanDefinition
      • 根据 bean 元素中的 class 属性和 parent 属性创建 BeanDefinition
      • 将 bean 标签上的属性设置到 BeanDefinition 中,一些未明确指定的属性采用代理 delegate 中的 defaults 值
      • 解析 bean 标签下的子标签,如 Property 、constructor-arg 等,将其键值对添加到 BeanDefinition 中
      • 返回 BeanDefinition
  • 相关阅读:
    Android开发学习之路--Content Provider之初体验
    [NOI2005] 维修数列
    递归算法对完全二叉树的前序遍历
    非递归算法对完全二叉树的前序遍历
    java中的多态
    poj1088滑雪
    在网页中插入flash
    如何采用批处理文件安装一个.dll文件,并且注册
    结构体指针和数组理解
    完全二叉树
  • 原文地址:https://www.cnblogs.com/feng-jq/p/10282200.html
Copyright © 2011-2022 走看看