3_默认标签解析

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {

        //import标签

                   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {

                            importBeanDefinitionResource(ele);

                   }

        //别名标签

                   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

                            doRegisterBeanDefinitions(ele);

                   }

         }

下面先看import标签的解析过程。通过以下代码可以发现,其实就是根据import标签中的resouce属性的值,在调用xml reader 进行解析新的资源文件。就是递归解析

protected void importBeanDefinitionResource(Element ele) {

        //获取需要resouce文件

                   String location = ele.getAttribute(RESOURCE_ATTRIBUTE);

                   if (!StringUtils.hasText(location)) {

                            getReaderContext().error("Resource location must not be empty", ele);

                            return;

                   }

 

                   // 解析路径你,就是如果使用${}这种格式。需要解析

                   location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

 

                   Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

 

                   //判断该资源是一个相对路径还是绝对路径

                   boolean absoluteLocation = false;

                   try {

                            absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();

                   }

                   catch (URISyntaxException ex) {

                            // cannot convert to an URI, considering the location relative

                            // unless it is the well-known Spring prefix "classpath*:"

                   }

 

                   // 绝对路径,获取到对应的xml reader继续解析该资源文件

                   if (absoluteLocation) {

                            try {

                                     int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);

                                     if (logger.isDebugEnabled()) {

                                               logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");

                                     }

                            }

                            catch (BeanDefinitionStoreException ex) {

                                     getReaderContext().error(

                                                        "Failed to import bean definitions from URL location [" + location + "]", ele, ex);

                            }

                   }

                   else {

                            // No URL -> considering resource location as relative to the current file.

                            try {

                                     int importCount;

                                     Resource relativeResource = getReaderContext().getResource().createRelative(location);

                                     if (relativeResource.exists()) {

                                               importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);

                                               actualResources.add(relativeResource);

                                     }

                                     else {

                                               String baseLocation = getReaderContext().getResource().getURL().toString();

                                               importCount = getReaderContext().getReader().loadBeanDefinitions(

                                                                 StringUtils.applyRelativePath(baseLocation, location), actualResources);

                                     }

                                     if (logger.isDebugEnabled()) {

                                               logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");

                                     }

                            }

                            catch (IOException ex) {

                                     getReaderContext().error("Failed to resolve current resource location", ele, ex);

                            }

                            catch (BeanDefinitionStoreException ex) {

                                     getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",

                                                        ele, ex);

                            }

                   }

                   Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);

                   getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));

         }

下面看下alias标签的解析<alias name="person" alias="bb"/>

首先解析出name字段。然后解析出alias字段,其实最终存放在了

beanFactory中的aliasMap中。会校验循环引用的存在。其实就是给一个bean起一个别名。

protected void processAliasRegistration(Element ele) {

                   String name = ele.getAttribute(NAME_ATTRIBUTE);

                   String alias = ele.getAttribute(ALIAS_ATTRIBUTE);

                   boolean valid = true;

                   if (!StringUtils.hasText(name)) {

                            getReaderContext().error("Name must not be empty", ele);

                            valid = false;

                   }

                   if (!StringUtils.hasText(alias)) {

                            getReaderContext().error("Alias must not be empty", ele);

                            valid = false;

                   }

                   if (valid) {

                            try {

                                     getReaderContext().getRegistry().registerAlias(name, alias);

                            }

                            catch (Exception ex) {

                                     getReaderContext().error("Failed to register alias '" + alias +

                                                        "' for bean with name '" + name + "'", ele, ex);

                            }

                            getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));

                   }

         }

下面看下bean标签的解析processBeanDefinition

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {

        //解析bean,设置bean的一些列属性

                   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));

                   }

         }

下面进入BeanDefinitionParserDelegate的parseBeanDefinitionElement  方法

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {

        //获取id和name属性。

                   String id = ele.getAttribute(ID_ATTRIBUTE);

                   String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

       //name可能是通过,;分隔符分割的多个

                   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;

                   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");

                            }

                   }

 

                   if (containingBean == null) {

                            checkNameUniqueness(beanName, aliases, ele);

                   }

        //创建beanDefinition

                   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

public AbstractBeanDefinition parseBeanDefinitionElement(

                            Element ele, String beanName, BeanDefinition containingBean) {

 

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

 

                   String className = null;

                   if (ele.hasAttribute(CLASS_ATTRIBUTE)) {

                            className = ele.getAttribute(CLASS_ATTRIBUTE).trim();

                   }

 

                   try {

                            String parent = null;

                            if (ele.hasAttribute(PARENT_ATTRIBUTE)) {

                                     parent = ele.getAttribute(PARENT_ATTRIBUTE);

                            }

                            AbstractBeanDefinition bd = createBeanDefinition(className, parent);

            //设置一些通用属性,比如override,init-method,scope.lazy-init

          

                            parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

                            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

            //解析meta标签

                            parseMetaElements(ele, bd);

           //解析 lookup-method

                            parseLookupOverrideSubElements(ele, bd.getMethodOverrides());

           //解析replace-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;

         }

经过上面的层层解析,最终将bean标签转换成了一个BeanDefinitionHolder对象。然后将beanDefinitionHolder对象。放入beanFactory中的beanDefinitionMap中。这样就保存了所有的bean的定义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值