zoukankan      html  css  js  c++  java
  • bean标签解析与注册

        protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
            BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
            if (bdHolder != null) {
                bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
    
                try {
                    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
                } catch (BeanDefinitionStoreException var5) {
                    this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
                }
    
                this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
            }
    
        }

      配置文件--读入并转换-->Element--解析-->bdHolder--注册-->BeanDifinition

    parseBeanDefinitionElement

      解析的主要阶段,把Element包含的bean的所有配置信息解析到bdHolder中,具体的解析过程调用了一个重载的parseBeanDefinitionElement方法。

        public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
            return this.parseBeanDefinitionElement(ele, (BeanDefinition)null);
        }
        public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
            String id = ele.getAttribute("id");
            String nameAttr = ele.getAttribute("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);
            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;
            }
        }

       一共做了三件事情

    • 解析id
    • 调用parseBeanDefinitionElement解析剩余属性,返回一个beanDifinition对象
    • 把beanDefinition对象封装到BeanDefinitionHolder对象中

      在具体的接续过程中,创建AbstractBeanDefinition作为bean信息的载体,调用针对不同属性的解析方法解析bean的属性并放入AbstractBeanDefinition中,所有this调用的方法都是用来接续bean具体属性的,如meta数据 lookupMethod等等。经过一系列复杂的调用才进入了真正解析属性的方法。

     public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
            this.parseState.push(new BeanEntry(beanName));
            String className = null;
            if (ele.hasAttribute("class")) {
                className = ele.getAttribute("class").trim();
            }
    
            try {
                String parent = null;
                if (ele.hasAttribute("parent")) {
                    parent = ele.getAttribute("parent");
                }
    
                AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
                this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
                bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
                this.parseMetaElements(ele, bd);
                this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
                this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
                this.parseConstructorArgElements(ele, bd);
                this.parsePropertyElements(ele, bd);
                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;
        }

    BeanDifinition

      BeanDifition是一个接口,BeanDefinition属性与bean的标签相对应。通过BeanDefinition把配置文件中bean标签定义的属性转换到Spring容器中,所以在解析bean标签前要先创建一个BeanDefinition对象。

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

      他有许多不同实现类,分别对应不同方法创建的Spring容器,如Annotation对应着注解创建的容器。

    注册BeanDefinition

      processBeanDefinition中BeanDefinitionReaderUtils.registerBeanDefinition方法。

     public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
            String beanName = definitionHolder.getBeanName();
            registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
            String[] aliases = definitionHolder.getAliases();
            if (aliases != null) {
                String[] var4 = aliases;
                int var5 = aliases.length;
    
                for(int var6 = 0; var6 < var5; ++var6) {
                    String alias = var4[var6];
                    registry.registerAlias(beanName, alias);
                }
            }
        }

      所有的Bean都被注册到register中,具体的分为两步

    • 根据BeanName注册
    • 根据别名注册

    根据BeanName注册

    • 针对methodOverrides校验
    • 从全局变量beanDefinitionMap中尝试获取BeanName,如果已经获得代表该Bean已经被注册,在不允许覆盖的情况下抛出异常

    把BeanName 和 Bean放入全局变量中beanDefinitionMap.put(beanName, beanDefinition),全局变量beanDefinitionMap就是IOC容器

        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 var9) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
                }
            }
    
            BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
            if (oldBeanDefinition != null) {
                if (!this.isAllowBeanDefinitionOverriding()) {
                    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 (!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 {
                if (this.hasBeanCreationStarted()) {
                    synchronized(this.beanDefinitionMap) {
                        this.beanDefinitionMap.put(beanName, beanDefinition);
                        List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
                        updatedDefinitions.addAll(this.beanDefinitionNames);
                        updatedDefinitions.add(beanName);
                        this.beanDefinitionNames = updatedDefinitions;
                        if (this.manualSingletonNames.contains(beanName)) {
                            Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
                            updatedSingletons.remove(beanName);
                            this.manualSingletonNames = updatedSingletons;
                        }
                    }
                } else {
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    this.beanDefinitionNames.add(beanName);
                    this.manualSingletonNames.remove(beanName);
                }
    
                this.frozenBeanDefinitionNames = null;
            }
    
            if (oldBeanDefinition != null || this.containsSingleton(beanName)) {
                this.resetBeanDefinition(beanName);
            }
    
        }
  • 相关阅读:
    leetcode-000-序
    统计学习方法:支撑向量机(SVM)
    统计学习方法:CART算法
    统计学习方法:最大熵模型
    〖Linux〗关于Linux软件包安装位置、版本查询
    〖Linux〗ltib的使用帮助
    〖Linux〗Debian 7.1.0 Wheezy使用ltib报错的解决办法
    〖Android〗把CM(Android)源代码导入eclipse的正确方法(2013-7-3)
    【Linux】eclipse juno 边框过大的调整方法
    【Android】在build/envsetup.sh中添加自己的命令(函数)
  • 原文地址:https://www.cnblogs.com/AshOfTime/p/10893304.html
Copyright © 2011-2022 走看看