Spring是如何解析XML并组装BeanDefinition存入BeanDefinitionMap的?

发布时间:2024年01月03日

环境

Spring Framework Version:5.3.x

Gradle Version:7.5.1

注意事项

阅读本文需要有一定的基础,并且要跟着调用链走,不然会很容易懵圈。

源码解读

入口

Demo.java
public static void main(String[] args) {
    //从这里进入
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
}
ClassPathXmlApplicationContext类
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        //看这里
        refresh();
    }
}

//refresh()
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //这个东西是Spring5.3.x的新特性,主要就是一个应用监控
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // 预刷新上下文
        prepareRefresh();

        // 获得新的beanFactory,主要就是刷新BeanFactory,跟进去看
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

       ...
    }
}


//obtainFreshBeanFactory()
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //主要看这个,这个是一个抽象方法,主要由子类实现,实现类有两种,默认是AbstractRefreshableApplicationContext类
    refreshBeanFactory();
    return getBeanFactory();
}
AbstractRefreshableApplicationContext类
@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        //主要看这个,加载Bean定义,这个方法也是一个抽象方法,主要关注实现类AbstractXmlApplicationContext
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

下面步入正题

AbstractXmlApplicationContext类

loadBeanDefinitions(DefaultListableBeanFactory beanFactory)

loadBeanDefinitions(DefaultListableBeanFactory beanFactory)这个方法大概做了哪些事?

  1. 创建一个新的xml bean定义阅读器,设置默认资源加载器与环境
  2. 使用当前上下文的配置重新给bean定义阅读器设置资源加载器与环境
  3. 初始化BeanDefinitionReader,配置XML验证
  4. 加载bean定义
// AbstractXmlApplicationContext.class
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 给bean工厂提供一个新的xml bean定义阅读器,并且指定默认的资源加载器与环境(env)
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    //使用当前上下文的配置重新给bean定义阅读器设置资源加载器与环境
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

  //初始化BeanDefinitionReader,配置XML验证
    initBeanDefinitionReader(beanDefinitionReader);
    //重点:加载Bean定义,点进去看
    loadBeanDefinitions(beanDefinitionReader);
}
loadBeanDefinitions(XmlBeanDefinitionReader reader)
  1. 获取配置资源
  2. 加载bean定义
// loadBeanDefinitions(beanDefinitionReader) 加载Bean定义
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    //获取配置资源
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    //获取配置资源地址,一般都走下面这个逻辑,因为我们通常都是 new ClassPathXmlApplicationContext("spring-context.xml");形式创建的spring容器
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        //加载bean定义,继续往里走
        reader.loadBeanDefinitions(configLocations);
    }
}

AbstractBeanDefinitionReader类

loadBeanDefinitions(String… locations)
//AbstractBeanDefinitionReader.class
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    int count = 0;
    for (String location : locations) {
        //直接看到这里,往里走
        count += loadBeanDefinitions(location);
    }
    return count;
}
loadBeanDefinitions(String location, @Nullable Set actualResources)
  1. 获取资源加载器
  2. 把资源地址转换成资源数组
  3. 加载bean定义
// loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources)
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
    //获取资源加载器,获取到的是ClassPathXmlApplicationContext,因为前面已经重新设置过了 beanDefinitionReader.setResourceLoader(this);
    ResourceLoader resourceLoader = getResourceLoader();
    //资源加载器为空直接抛异常
    if (resourceLoader == null) {
        throw new BeanDefinitionStoreException(
            "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
        try {
            //把资源地址转换成资源数组
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            //加载bean定义,主要看这里
            int count = loadBeanDefinitions(resources);
            if (actualResources != null) {
                Collections.addAll(actualResources, resources);
            }
            if (logger.isTraceEnabled()) {
                logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
            }
            return count;
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                "Could not resolve bean definition resource pattern [" + location + "]", ex);
        }
    }
    else {
        // Can only load single resources by absolute URL.
        Resource resource = resourceLoader.getResource(location);
        int count = loadBeanDefinitions(resource);
        if (actualResources != null) {
            actualResources.add(resource);
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
        }
        return count;
    }
}
loadBeanDefinitions(Resource… resources)
//loadBeanDefinitions(Resource... resources)
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, "Resource array must not be null");
    int count = 0;
    for (Resource resource : resources) {
        //继续往下走
        count += loadBeanDefinitions(resource);
    }
    return count;
}

XmlBeanDefinitionReader类

loadBeanDefinitions(EncodedResource encodedResource)
  1. 真正的开始加载bean定义
//XmlBeanDefinitionReader.class  loadBeanDefinitions(EncodedResource encodedResource)
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();

    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());
        }
        //这里才是真正的开始加载bean定义了,继续往里走
        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(InputSource inputSource, Resource resource)
  1. 解析xml
  2. 注册bean定义
//由于代码太长,我精简了一下代码,留下主要的
//doLoadBeanDefinitions(InputSource inputSource, Resource resource)
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
    try {
        //真正的开始解析xml了,使用JAXP解析器进行解析xml,具体源码放在下面,详见DefaultDocumentLoader类
        Document doc = doLoadDocument(inputSource, resource);
        //注册bean定义
        int count = registerBeanDefinitions(doc, resource);
        return count;
    }
    catch (BeanDefinitionStoreException ex) {
        throw ex;
    }
    ...
}
doLoadDocument(InputSource inputSource, Resource resource)
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    //调用文档加载器加载xml
    return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
                                            getValidationModeForResource(resource), isNamespaceAware());
}
DefaultDocumentLoader类
  1. 通过反射创建文档构建工厂并进行xsd规范校验
  2. 创建文档构建器
  3. 使用jaxp解析器解析xml并返回Document对象
//DefaultDocumentLoader.class
@Override
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
                             ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
    //通过反射创建文档构建工厂并进行xsd规范校验
    DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
    if (logger.isTraceEnabled()) {
        logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
    }
    //创建文档构建器
    DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
    //解析xml并返回Document对象
    return builder.parse(inputSource);
}

至此,xml已经解析完成,下面就是从文档对象中取出bean相关的数据并组装成BeanDefinition存入BeanDefinitionMap中

小总结

简单来说,解析xml其实就是调用jaxp的api进行解析,解析完成后返回一个文档对象,然后根据规则来取出数据并组装,就这么简单。

回到XmlBeanDefinitionReader类中的registerBeanDefinitions(Document doc, Resource resource)
  1. 创建文档读取器
  2. 注册bean定义
//registerBeanDefinitions(Document doc, Resource resource)
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    //创建bean定义文档读取器
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    int countBefore = getRegistry().getBeanDefinitionCount();
    //注册bean定义,继续往下走
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

DefaultBeanDefinitionDocumentReader类

registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
//DefaultBeanDefinitionDocumentReader.class
//registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    //真正注册bean定义的方法
    doRegisterBeanDefinitions(doc.getDocumentElement());
}
doRegisterBeanDefinitions(Element root)
  1. 预处理xml(空实现)
  2. 解析bean定义
  3. 后处理xml(空实现)
//doRegisterBeanDefinitions(doc.getDocumentElement())
protected void doRegisterBeanDefinitions(Element root) {
    // Any nested <beans> elements will cause recursion in this method. In
    // order to propagate and preserve <beans> default-* attributes correctly,
    // keep track of the current (parent) delegate, which may be null. Create
    // the new (child) delegate with a reference to the parent for fallback purposes,
    // then ultimately reset this.delegate back to its original (parent) reference.
    // this behavior emulates a stack of delegates without actually necessitating one.
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
        if (StringUtils.hasText(profileSpec)) {
            String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            // 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;
            }
        }
    }


    //预处理xml
    preProcessXml(root);
    //解析bean定义
    parseBeanDefinitions(root, this.delegate);
    //后处理xml
    postProcessXml(root);

    this.delegate = parent;
}
parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
  1. 处理xml,拿到beans标签里的集合
  2. 解析默认元素(import、alias、bean、beans等标签)
//parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    if (delegate.isDefaultNamespace(root)) {
        //处理xml,拿到beans标签里的集合
        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 {
        delegate.parseCustomElement(root);
    }
}
parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
//parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    //这里的判断就是对应的标签,需要处理的标签,我们现在是解析bean,看到对应的处理器processBeanDefinition(ele, delegate);
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        //看这里
        processBeanDefinition(ele, delegate);
    }
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}
processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)

我们先看delegate.parseBeanDefinitionElement(ele);再看BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

  1. 解析bean标签,组装BeanDefinitionHolder
  2. 注册bean定义,把bean定义放到Map中
  3. 发布注册事件
//processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    //解析bean标签的元素,组装成bean定义持有者,往里跟一下
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            //注册bean定义,把bean定义放到Map中
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                                     bdHolder.getBeanName() + "'", ele, ex);
        }
        // 发布注册事件
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

BeanDefinitionParserDelegate类

  1. 从标签里获取到id和name的值
  2. 解析bean定义的元素(parseBeanDefinitionElement(ele, beanName, containingBean);)重点看这个!!!
  3. 组装成BeanDefinitionHolder并返回
//parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean)
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
    //从标签里获取到id和name的值
    String id = ele.getAttribute(ID_ATTRIBUTE);
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    List<String> aliases = new ArrayList<>();
    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.isTraceEnabled()) {
            logger.trace("No XML 'id' specified - using '" + beanName +
                         "' as bean name and " + aliases + " as aliases");
        }
    }

    if (containingBean == null) {
        checkNameUniqueness(beanName, aliases, ele);
    }
	//解析bean定义的元素,我们跟进去看看
    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.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;
}




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

这里主要说一下流程,然后带看一下createBeanDefinition方法,其他的具体源码就不过多讲解了,感兴趣的uu可以自己去阅读下源码,这里就不过多赘述了

  1. 创建bean定义
  2. 解析bean定义属性
  3. 解析元数据元素
  4. 解析lookup-method标签
  5. 解析replace-method标签
  6. 解析构造器参数
  7. 解析标签及里面的标签
  8. 解析自定义bean名称的元素
  9. 返回解析好的bean定义
//parseBeanDefinitionElement(ele, beanName, containingBean)
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
    Element ele, String beanName, @Nullable BeanDefinition containingBean) {
    //解析的状态管理,解析完之后会pop,主要用于异常处理,记录当前解析状态
    this.parseState.push(new BeanEntry(beanName));

    String className = null;
    if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
        className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
    }
    String parent = null;
    if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
        parent = ele.getAttribute(PARENT_ATTRIBUTE);
    }

    try {
        //创建bean定义
        AbstractBeanDefinition bd = createBeanDefinition(className, parent);
        //解析bean定义属性
        parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
        bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
        //解析元数据元素
        parseMetaElements(ele, bd);
        //解析lookup-method标签
        parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
        //解析replace-method标签
        parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
        //解析构造器参数
        parseConstructorArgElements(ele, bd);
        //解析<property>标签及里面的标签
        parsePropertyElements(ele, bd);

        //解析自定义bean名称的元素
        parseQualifierElements(ele, bd);

        bd.setResource(this.readerContext.getResource());
        bd.setSource(extractSource(ele));
        //返回解析好的bean定义
        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;
}

BeanDefinitionReaderUtils类

createBeanDefinition(@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader)

简单来说这里就设置了个beanClass,如果ClassLoader不为空,直接通过反射加载类并赋值给beanClass,不然就把beanClass设置为类名

public static AbstractBeanDefinition createBeanDefinition(@Nullable String parentName, @Nullable String className, 
                                                          @Nullable ClassLoader classLoader) throws ClassNotFoundException {
    GenericBeanDefinition bd = new GenericBeanDefinition();
    bd.setParentName(parentName);
    if (className != null) {
        //如果ClassLoader不为空,使用反射加载bean
        if (classLoader != null) {
            bd.setBeanClass(ClassUtils.forName(className, classLoader));
        } else {
            //设置bean类名
            bd.setBeanClassName(className);
        }
    }
    return bd;
}

总的来说就是组装BeanDefinition,都是从Element对象取数据并设置到BeanDefinition里

至此,从Element对象里取出数据组装成BeanDefinition源码解读完毕,接下来就是如何存入BeanDefinitionMap中了

回到DefaultBeanDefinitionDocumentReader类中的processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)方法

// 看到这行,注册Bean定义,把BeanDefinition存入Map中,我们点进去看看
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
    									throws BeanDefinitionStoreException {

    // 从BeanDefinitionHolder中获取bean名称
    String beanName = definitionHolder.getBeanName();
    //注册bean定义(重点),点进去看实现,注意:这里是个接口,进去看他的默认实现类 => DefaultListableBeanFactory
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // 如果有别名的话.也用别名注册一个
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

DefaultListableBeanFactory类

registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
  1. 先验证下BeanDefinition
  2. 从beanDefinitionMap里取一遍,看看有没有,有的话就做一系列的校验并重新写入beanDefinitionMap
  3. 这里分两种情况
    1. 容器已创建
      1. 加锁
      2. 注册bean
      3. 先把beanName存入updatedDefinitions中,再把updatedDefinitions赋值给beanDefinitionNames
      4. 移除手工单例名称
    2. 容器第一次创建
      1. 注册bean
      2. 把beanName保存到beanDefinitionNames中
      3. 移除手工单例名称

大概就这么多

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

    //验证BeanDefinition,就是校验一下方法重载和工厂方法不能同时存在,感兴趣的uu可以自己去阅读下源码,这里就不过多赘述了
    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                                                   "Validation of bean definition failed", ex);
        }
    }
    //先从缓存里获取,如果能获取到,那就重新put
    BeanDefinition 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_INFRASTRUCTURE
            if (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 {
        //检查这个工厂的bean创建阶段是否已经开始,如果已经创建过了,判断结果为true,否则走else(容器第一次创建必然走else)
        if (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;
                removeManualSingletonName(beanName);
            }
        }
        else {
            // 仍在启动注册阶段,直接向beanDefinitionMap put元素,key为bean名称,value为bean定义
            this.beanDefinitionMap.put(beanName, beanDefinition);
            //添加bean定义名称到beanDefinitionNames里
            this.beanDefinitionNames.add(beanName);
            //移除手工注入单例名称
            removeManualSingletonName(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }
    //如果existingDefinition不为空 or 单例池里包含该bean,直接重置BeanDefinition(根据beanName清除BeanDefinition与销毁对象)
    if (existingDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
    else if (isConfigurationFrozen()) {
        clearByTypeCache();
    }
}

至此,我们就完成了从文档对象中取出bean相关的数据并组装成BeanDefinition存入BeanDefinitionMap中的源码解读

小总结

说得宽泛一点大体流程就是:

  1. 解析文档对象组装BeanDefintionHolder
  2. 注册BeanDefinition
  3. 发布注册事件

最后总结

基本上就以下几点

  1. 使用jaxp 解析器来解析xml,返回Document对象(ps:不知道jaxp解析器的可自行百度了解一下)
  2. 解析文档对象组装BeanDefintionHolder
  3. 注册BeanDefinition(即BeanDefinition存入BeanDefinitionMap中)
  4. 发布注册事件
文章来源:https://blog.csdn.net/qq_43599126/article/details/135251184
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。