property 标签的解析算是相对复杂的,其他标签(meta、constructor-arg 等)的解析过程大体是类似的,不再一一分析 。
经过 BeanDefinitionParserDelegate#parseBeanDefinitionElement 方法的解析和封装后,就得到了保存我们自定义 bean 信息的 BeanDefinition,即 GenericBeanDefinition 。Spring 又把 BeanDefinition 和别名信息封装成了 BeanDefinitionHolder:
public class BeanDefinitionParserDelegate {public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {String id = ele.getAttribute(ID_ATTRIBUTE);String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);// ...// 解析后得到的 BeanDefinitionAbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);if (beanDefinition != null) {// ...String[] aliasesArray = StringUtils.toStringArray(aliases);return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);}return null;}}此外,在向 IoC 容器注册之前,还有一个 decorateBeanDefinitionIfRequired 方法,它主要是用来处理默认名称空间(即 www.springframework.org/schema/bean… )之外的 bean 定义,比如 <tx>、<context> 等,这里仍然先沿着主线走,暂不深入分析 。
接下来就是将 BeanDefinition 注册到 IoC 容器:
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {// ...protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {// 解析后的 BeanDefinition 封装成的 BeanDefinitionHolderBeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) {// 处理非默认名称空间的 beanbdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// Register the final decorated instance.// 注册 BeanDefinitionBeanDefinitionReaderUtils.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));}}}public abstract class BeanDefinitionReaderUtils {// ...public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {// Register bean definition under primary name.String beanName = definitionHolder.getBeanName();registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// Register aliases for bean name, if any.String[] aliases = definitionHolder.getAliases();if (aliases != null) {for (String alias : aliases) {registry.registerAlias(beanName, alias);}}}}IoC 容器是哪个?如何注册呢?
前文提到过,Spring 默认的 IoC 容器是 DefaultListableBeanFactory,来看下它的继承结构:

文章插图
可以看到 DefaultListableBeanFactory 实现了 BeanDefinitionRegistry 接口 。
所谓的“注册”到 IoC 容器,其实就是把 BeanDefinition 保存到了 DefaultListableBeanFactory 持有的一个 Map 中,如下:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {// ...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 ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);}}// 获取已存在的 BeanDefinitionBeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);if (existingDefinition != null) {if (!isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);}// 这几个异常信息是不是有点眼熟?else if (existingDefinition.getRole() < beanDefinition.getRole()) {// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTUREif (logger.isInfoEnabled()) {logger.info("Overriding user-defined bean definition for bean '" + beanName +"' with a framework-generated bean definition: replacing [" +existingDefinition + "] with [" + beanDefinition + "]");}}else if (!beanDefinition.equals(existingDefinition)) {if (logger.isDebugEnabled()) {logger.debug("Overriding bean definition for bean '" + beanName +"' with a different definition: replacing [" + existingDefinition +"] with [" + beanDefinition + "]");}}else {if (logger.isTraceEnabled()) {logger.trace("Overriding bean definition for bean '" + beanName +"' with an equivalent definition: replacing [" + existingDefinition +"] with [" + beanDefinition + "]");}}this.beanDefinitionMap.put(beanName, beanDefinition);}else {if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)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;removeManualSingletonName(beanName);}}else {// 注册到 Map 中// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);removeManualSingletonName(beanName);}this.frozenBeanDefinitionNames = null;}if (existingDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}else if (isConfigurationFrozen()) {clearByTypeCache();}}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 白茶茶饼是怎么做的,香芋奶茶怎么做呢
- 前后端分离项目,如何解决跨域问题?
- Xml序列化
- 夜间咳嗽是怎么回事
- 夏季吃什么可以排毒
- 晚上磨牙怎么治疗
- 睡觉磨牙怎么治疗?
- 水果被冻后会产生毒物质吗
- bite是什么意思中文意思是什么?bite和bit是什么关系
- 秋季预防感冒和鼻炎
