《Spring系列》第2章 解析XML获取Bean

一、基础代码

Spring加载bean实例的代码

public static void main(String[] args) throws IOException {
    // 1.获取资源
    Resource resource = new ClassPathResource("bean.xml");
    // 2.获取BeanFactory
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    // 3.获取资源的解析器
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
    // 4.装载资源
    reader.loadBeanDefinitions(resource);

    // 5.获取Bean实例
    Book book = factory.getBean(Book.class);
    System.out.println(book);
}

这段代码是 Spring 中编程式使用 IoC 容器,通过这四段简单的代码,我们可以初步判断 IoC 容器的使用过程。整个过程就分为三个步骤:

资源定位。我们一般用外部资源来描述 Bean 对象,所以在初始化 IoC 容器的第一步就是需要定位这个外部资源。

装载。装载就是 BeanDefinition 的载入。BeanDefinitionReader 读取、解析 Resource 资源,也就是将用户定义的 Bean 表示成 IoC 容器的内部数据结构:BeanDefinition

注册。向 IoC 容器注册在第二步解析好的 BeanDefinition,这个过程是通过BeanDefinitionRegistry接口来实现的。在 IoC 容器内部其实是将第二个过程解析得到的BeanDefinition注入到一个HashMap容器中,IoC 容器就是通过这个HashMap来维护这些BeanDefinition的。

​ 1)在这里需要注意的一点是这个过程并没有完成依赖注入(Bean 创建),Bean 创建是发生在应用第一次调用getBean()方法,向容器索要 Bean 时。
​ 2)当然我们可以通过设置预处理,即对某个 Bean 设置lazyinit = false 属性,那么这个 Bean 的依赖注入就会在容器初始化的时候完成。

简单点说,上面步骤的结果是:XML Resource -> XML Document -> Bean Definition

二、BeanDefinition

上面讲完了介绍到我们解析的Bean标签会封装成BeanDefinition,那么接下来看一下

1.基础介绍

org.springframework.beans.factory.config.BeanDefinition ,是一个接口,它描述了一个 Bean 实例的定义,包括属性值、构造方法值和继承自它的类的更多信息。代码如下:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
 	
    // 其中方法就不粘贴了,太多了
}

2.BeanDefinition 的父关系

BeanDefinition 继承 AttributeAccessorBeanMetadataElement 接口。两个接口定义如下:

org.springframework.cor.AttributeAccessor 接口,定义了与其它对象的(元数据)进行连接和访问的约定,即对属性的修改,包括获取、设置、删除。代码如下:

public interface AttributeAccessor {

   void setAttribute(String name, @Nullable Object value);

   @Nullable
   Object getAttribute(String name);

   @Nullable
   Object removeAttribute(String name);

   boolean hasAttribute(String name);

   String[] attributeNames();
}

org.springframework.beans.BeanMetadataElement 接口,Bean 元对象持有的配置元素可以通过 getSource() 方法来获取。代码如下:

public interface BeanMetadataElement {

   @Nullable
   default Object getSource() {
      return null;
   }
}

3.BeanDefinition 的子关系

在这里插入图片描述

我们常用的三个实现类有:

  • org.springframework.beans.factory.support.ChildBeanDefinition
  • org.springframework.beans.factory.support.RootBeanDefinition
  • org.springframework.beans.factory.support.GenericBeanDefinition
  1. ChildBeanDefinitionRootBeanDefinitionGenericBeanDefinition 三者都继承 AbstractBeanDefinition 抽象类,即 AbstractBeanDefinition 对三个子类的共同的类信息进行抽象。
  2. 如果配置文件中定义了父 和 子 ,则父 用 RootBeanDefinition 表示,子 用 ChildBeanDefinition 表示,而没有父 的就使用RootBeanDefinition 表示。
  3. GenericBeanDefinition 为一站式服务类。

三、调用链

在这里插入图片描述

1.loadBeanDefinitions() 加载

加载BeanDefinition

// XmlBeanDefinitionReader XML解析类
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
   // 将Resource资源封装成EncodedResource,封装的原因是为了进行编码,保证内容读取的正确性
   return loadBeanDefinitions(new EncodedResource(resource));
}
// XmlBeanDefinitionReader XML解析类
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
   Assert.notNull(encodedResource, "EncodedResource must not be null");
   if (logger.isTraceEnabled()) {
      logger.trace("Loading XML bean definitions from " + encodedResource);
   }

   // 获取已经加载过的资源
   Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

   // 将当前资源加入记录中,如果已存在,则抛出异常
   // 主要为了避免一个EncodedResource在加载时,还没加载完成,又加载自身,从而导致死循环
   if (!currentResources.add(encodedResource)) {
      throw new BeanDefinitionStoreException(
            "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
   }

   // 获取输入流
   try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
      InputSource inputSource = new InputSource(inputStream);
      if (encodedResource.getEncoding() != null) {
         // 设置编码
         inputSource.setEncoding(encodedResource.getEncoding());
      }
      // **核心逻辑部分,执行加载 BeanDefinition
      return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
   }
   catch (IOException ex) {
      throw new BeanDefinitionStoreException(
            "IOException parsing XML document from " + encodedResource.getResource(), ex);
   }
   finally {
      // 缓存中剔除该资源,代表加载完了该文件
      currentResources.remove(encodedResource);
      if (currentResources.isEmpty()) {
         this.resourcesCurrentlyBeingLoaded.remove();
      }
   }
}

-> doLoadBeanDefinitions()

// XmlBeanDefinitionReader XML解析类
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {

   try {
      // 获取XML Document实例
      Document doc = doLoadDocument(inputSource, resource);
      // 根据 Document 实例,注册 Bean 信息
      int count = registerBeanDefinitions(doc, resource);
      if (logger.isDebugEnabled()) {
         logger.debug("Loaded " + count + " bean definitions from " + resource);
      }
      return count;
   }
   catch (BeanDefinitionStoreException ex) {
      throw ex;
   }
   catch (SAXParseException ex) {
      throw new XmlBeanDefinitionStoreException(resource.getDescription(),
            "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
   }
   catch (SAXException ex) {
      throw new XmlBeanDefinitionStoreException(resource.getDescription(),
            "XML document from " + resource + " is invalid", ex);
   }
   catch (ParserConfigurationException ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
            "Parser configuration exception parsing XML from " + resource, ex);
   }
   catch (IOException ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
            "IOException parsing XML document from " + resource, ex);
   }
   catch (Throwable ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
            "Unexpected exception parsing XML document from " + resource, ex);
   }
}

2.doLoadDocument()

XML文件解析成Docuemnt

private DocumentLoader documentLoader = new DefaultDocumentLoader();

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
   return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
         getValidationModeForResource(resource), isNamespaceAware());
}
// DefaultDocumentLoader 默认的文档加载器
@Override
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
      ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

   DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
   if (logger.isTraceEnabled()) {
      logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
   }
   DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
   return builder.parse(inputSource);
}

3.registerBeanDefinitions() 开始注册

注册BeanDefinition

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
   // <1>创建对象BeanDefinitionDocumentReader
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   // <2>获取已注册的BeanDefinition数量
   int countBefore = getRegistry().getBeanDefinitionCount();
   // <3>创建XmlReaderContext
   // <4>注册新的Bean
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   // <5>两个相减,返回注册成功的数量
   return getRegistry().getBeanDefinitionCount() - countBefore;
}

-> registerBeanDefinitions()

@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
   this.readerContext = readerContext;
   doRegisterBeanDefinitions(doc.getDocumentElement());
}

-> doRegisterBeanDefinitions()

该方法特殊处理profile属性,然后进行解析

protected void doRegisterBeanDefinitions(Element root) {
   // 记录老的 BeanDefinitionParserDelegate 对象
   BeanDefinitionParserDelegate parent = this.delegate;
   // 创建 BeanDefinitionParserDelegate 对象,并进行设置到 delegate
   // *** 它负责解析Document的各种对象
   this.delegate = createDelegate(getReaderContext(), root, parent);

   // 检查 <beans /> 根标签的命名空间是否为空,或者是 http://www.springframework.org/schema/beans
   if (this.delegate.isDefaultNamespace(root)) {
      // 处理profile属性
      String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
      if (StringUtils.hasText(profileSpec)) {
         // 使用分隔符切分,可能有多个 profile 。
         String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
               profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
         // 如果所有 profile 都无效,则不进行注册
         // We cannot use Profiles.of(...) since profile expressions are not supported
         // in XML config. See SPR-12458 for details.
         if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
            if (logger.isDebugEnabled()) {
               logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                     "] not matching: " + getReaderContext().getResource());
            }
            return;
         }
      }
   }

   // 解析前处理, 空实现
   preProcessXml(root);
   // 解析
   parseBeanDefinitions(root, this.delegate);
   // 解析后处理, 空实现
   postProcessXml(root);

   this.delegate = parent;
}


protected void preProcessXml(Element root) {
}

protected void postProcessXml(Element root) {
}

4.parseBeanDefinitions() 分类解析

下面代码中会区分2类,

  1. 默认命名空间,例如:<bean id="book" class="com.h3c.ss.Book"></bean>
  2. 自定义注解方式,例如:<tx:annotation-driven>
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   // <1>如果根节点使用默认命名空间,执行默认解析
   if (delegate.isDefaultNamespace(root)) {
      // 遍历子节点,也就是XML文件中的内容
      NodeList nl = root.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
         Node node = nl.item(i);
         if (node instanceof Element) {
            Element ele = (Element) node;
            // 如果该节点使用默认命名空间,执行默认解析
            if (delegate.isDefaultNamespace(ele)) {
               parseDefaultElement(ele, delegate);
            }
            else {
               // 否则执行自定义解析
               delegate.parseCustomElement(ele);
            }
         }
      }
   }
   else {
      //<2> 根节点非默认命名空间,执行自定义解析
      delegate.parseCustomElement(root);
   }
}

-> parseDefaultElement() 解析默认命名空间

public static final String BEAN_ELEMENT = "bean";
public static final String IMPORT_ELEMENT = "import";
public static final String ALIAS_ATTRIBUTE = "alias";
public static final String NESTED_BEANS_ELEMENT = "beans";


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);
   }
   // 解析嵌套的bean
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      // recurse
      doRegisterBeanDefinitions(ele);
   }
}

-> parseCustomElement() 自定义解析

5.importBeanDefinitionResource() 解析import标签

6.processBeanDefinition() 解析bean标签

解析工作分为三步:

  1. 解析默认标签。
  2. 解析默认标签后下得自定义标签。
  3. 注册解析后的 BeanDefinition 。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   // <1> 如果解析成功,则返回 BeanDefinitionHolder 对象。而 BeanDefinitionHolder 为 name 和 alias 的 BeanDefinition 对象
   // 如果解析失败,则返回 null 。
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
      // <2> 解析默认标签后下得自定义标签
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         // <3> 进行 BeanDefinition 的注册
         // 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));
   }
}

-> 第1步:解析beanName

在这里插入图片描述

  1. 解析 idname 属性,确定 aliases 集合
  2. 检测 beanName 是否唯一
  3. 对属性进行解析并封装成 AbstractBeanDefinition 实例 beanDefinition
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
   return parseBeanDefinitionElement(ele, null);
}

@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
   // 获取Id 和 name
   String id = ele.getAttribute(ID_ATTRIBUTE);
   String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

   // 解析name
   List<String> aliases = new ArrayList<>();
   if (StringUtils.hasLength(nameAttr)) {
      // name属性可以存在多个,可以以不同的分隔符间隔,这里就是用于拆分的工具类
      String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
      aliases.addAll(Arrays.asList(nameArr));
   }

   // bean名称优先使用id
   String beanName = id;
   if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
      // 没有id,则默认使用别名的第1个
      beanName = aliases.remove(0);
      if (logger.isTraceEnabled()) {
         logger.trace("No XML 'id' specified - using '" + beanName +
               "' as bean name and " + aliases + " as aliases");
      }
   }

   // 检查bean是否存在重名现象
   if (containingBean == null) {
      checkNameUniqueness(beanName, aliases, ele);
   }

   // 解析属性,构造 AbstractBeanDefinition 对象
   AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
   if (beanDefinition != null) {
      // beanName如果不存在,则需要系统生成
      if (!StringUtils.hasText(beanName)) {
         try {
            // containingBean传过来的就是Null
            if (containingBean != null) {
               beanName = BeanDefinitionReaderUtils.generateBeanName(
                     beanDefinition, this.readerContext.getRegistry(), true);
            }
            else {
               // 生成唯一的 beanName
               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.isTraceEnabled()) {
               logger.trace("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;
}

-> 第2步:解析内部标签

第2步的入口来自第1步
在这里插入图片描述

@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
      Element ele, String beanName, @Nullable BeanDefinition containingBean) {

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

   // 解析 class 属性
   String className = null;
   if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
      className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
   }
   // 解析 parent 属性
   String parent = null;
   if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
      parent = ele.getAttribute(PARENT_ATTRIBUTE);
   }

   try {
      // 创建用于承载属性的 AbstractBeanDefinition 实例
      // 创建的类型为: GenericBeanDefinition
      AbstractBeanDefinition bd = createBeanDefinition(className, parent);
    
      // 解析默认 bean 的各种属性
      parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
      // 提取 description
      bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

      // tips:
      // 下面的一堆是解析 <bean>......</bean> 内部的子元素,
      // 解析出来以后的信息都放到 bd 的属性中
      // 解析元数据 <meta />
      parseMetaElements(ele, bd);
      // 解析 lookup-method 属性 <lookup-method />
      parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
      // 解析 replaced-method 属性 <replaced-method />
      parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

      // 解析构造函数参数 <constructor-arg />
      parseConstructorArgElements(ele, bd);
      // 解析 property 子元素 <property />
      parsePropertyElements(ele, bd);
      // 解析 qualifier 子元素 <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;
}

-> 第3步:解析bean属性

第3步的入口来自第2步
在这里插入图片描述

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
      @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

   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));
   }
   else if (containingBean != null) {
      // Take default from containing bean in case of an inner bean definition.
      bd.setScope(containingBean.getScope());
   }

   // 解析abstract属性
   if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
      bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
   }

   // 解析lazy-init属性
   String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
   if (isDefaultValue(lazyInit)) {
      lazyInit = this.defaults.getLazyInit();
   }
   bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

   String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
   bd.setAutowireMode(getAutowireMode(autowire));

   if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
      String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
      bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
   }

   String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
   if (isDefaultValue(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));
   }

   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);
      bd.setInitMethodName(initMethodName);
   }
   else 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 if (this.defaults.getDestroyMethod() != null) {
      bd.setDestroyMethodName(this.defaults.getDestroyMethod());
      bd.setEnforceDestroyMethod(false);
   }

   if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
      bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
   }
   if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
      bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
   }

   return bd;
}

7.registerBeanDefinition() 注册

从第6步开始,解析完bean标签的各个属性,然后就是要注册到容器中了

// BeanDefinitionReaderUtils#registerBeanDefinition()  该方式是1个工具类,一个中转而已

public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException {

   // 获取beanName
   // 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);
      }
   }
}

-> registerBeanDefinition() 注册bean

处理过程如下:

  • <1> 对 BeanDefinition 进行校验,该校验也是注册过程中的最后一次校验了,主要是对 AbstractBeanDefinitionmethodOverrides 属性进行校验。
  • <2> 根据 beanName 从缓存中获取 BeanDefinition 对象。
  • <3> 如果缓存中存在,则根据 allowBeanDefinitionOverriding 标志来判断是否允许覆盖。如果允许则直接覆盖。否则,抛出 BeanDefinitionStoreException 异常。
  • <4>若缓存中没有指定 beanNameBeanDefinition,则判断当前阶段是否已经开始了 Bean 的创建阶段?如果是,则需要对 beanDefinitionMap 进行加锁控制并发问题,否则直接设置即可。
  • <5> 若缓存中存在该 beanName 或者单例 bean 集合中存在该 beanName ,则调用 #resetBeanDefinition(String beanName) 方法,重置 BeanDefinition 缓存。
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {

   // <1> 校验 BeanDefinition 。
   // 校验 beanName 与 beanDefinition 非空
   Assert.hasText(beanName, "Bean name must not be empty");
   Assert.notNull(beanDefinition, "BeanDefinition must not be null");

   // 这是注册前的最后一次校验了,主要是对属性 methodOverrides 进行校验。
   if (beanDefinition instanceof AbstractBeanDefinition) {
      try {
         ((AbstractBeanDefinition) beanDefinition).validate();
      }
      catch (BeanDefinitionValidationException ex) {
         throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
               "Validation of bean definition failed", ex);
      }
   }

   // <2> 从缓存中获取指定 beanName 的 BeanDefinition
   BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
   // <3> 如果已经存在
   // 获取到则代表已经存在
   if (existingDefinition != null) {
      // 如果配置了不允许覆盖,则抛出异常
      if (!isAllowBeanDefinitionOverriding()) {
         throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
      }
      // 覆盖 beanDefinition 大于 被覆盖的 beanDefinition 的 ROLE ,打印 info 日志
      else if (existingDefinition.getRole() < beanDefinition.getRole()) {
         // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
         if (logger.isInfoEnabled()) {
            logger.info("Overriding user-defined bean definition for bean '" + beanName +
                  "' with a framework-generated bean definition: replacing [" +
                  existingDefinition + "] with [" + beanDefinition + "]");
         }
      }
      // 覆盖 beanDefinition 与 被覆盖的 beanDefinition 不相同,打印 debug 日志
      else if (!beanDefinition.equals(existingDefinition)) {
         if (logger.isDebugEnabled()) {
            logger.debug("Overriding bean definition for bean '" + beanName +
                  "' with a different definition: replacing [" + existingDefinition +
                  "] with [" + beanDefinition + "]");
         }
      }
      // 其它,打印 debug 日志
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Overriding bean definition for bean '" + beanName +
                  "' with an equivalent definition: replacing [" + existingDefinition +
                  "] with [" + beanDefinition + "]");
         }
      }
      // *************允许覆盖,直接覆盖原有的 BeanDefinition 到 beanDefinitionMap 中*************
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   else {
      // <4> 如果未存在
      // 检测创建 Bean 阶段是否已经开启,如果开启了则需要对 beanDefinitionMap 进行并发控制
      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 {
         // 注册到容器中
         this.beanDefinitionMap.put(beanName, beanDefinition);
         // 注册beanName
         this.beanDefinitionNames.add(beanName);
         removeManualSingletonName(beanName);
      }
      this.frozenBeanDefinitionNames = null;
   }

   if (existingDefinition != null || containsSingleton(beanName)) {
      // <5> 重新设置 beanName 对应的缓存
      resetBeanDefinition(beanName);
   }
   else if (isConfigurationFrozen()) {
      clearByTypeCache();
   }
}

-> registerAlias() 注册别名

把别名和beanName的映射关系添加到1个Map里面,key=别名,value=beanName

// SimpleAliasRegistry.java

@Override
public void registerAlias(String name, String alias) {
   Assert.hasText(name, "'name' must not be empty");
   Assert.hasText(alias, "'alias' must not be empty");
   synchronized (this.aliasMap) {
      // name == alias 则去掉alias
      if (alias.equals(name)) {
         this.aliasMap.remove(alias);
         if (logger.isDebugEnabled()) {
            logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
         }
      }
      else {
         // 获取 alias 已注册的 beanName
         String registeredName = this.aliasMap.get(alias);
         // 当注册的beanName存在
         if (registeredName != null) {
            // 相同,则 return ,无需重复注册
            if (registeredName.equals(name)) {
               // An existing alias - no need to re-register
               return;
            }
            // 不允许覆盖,则抛出 IllegalStateException 异常
            if (!allowAliasOverriding()) {
               throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
                     name + "': It is already registered for name '" + registeredName + "'.");
            }
            if (logger.isDebugEnabled()) {
               logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
                     registeredName + "' with new target name '" + name + "'");
            }
         }
         // 校验,是否存在循环指向
         checkForAliasCircle(name, alias);
         // 注册 alias
         this.aliasMap.put(alias, name);
         if (logger.isTraceEnabled()) {
            logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
         }
      }
   }
}

允许覆盖,则抛出 IllegalStateException 异常
if (!allowAliasOverriding()) {
throw new IllegalStateException(“Cannot define alias '” + alias + “’ for name '” +
name + “': It is already registered for name '” + registeredName + “'.”);
}
if (logger.isDebugEnabled()) {
logger.debug(“Overriding alias '” + alias + “’ definition for registered name '” +
registeredName + “’ with new target name '” + name + “'”);
}
}
// 校验,是否存在循环指向
checkForAliasCircle(name, alias);
// 注册 alias
this.aliasMap.put(alias, name);
if (logger.isTraceEnabled()) {
logger.trace(“Alias definition '” + alias + “’ registered for name '” + name + “'”);
}
}
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为人师表好少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值