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