千家信息网

如何进行BeanDefinition的定位,加载和注册

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇文章给大家分享的是有关如何进行BeanDefinition的定位,加载和注册,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。以XmlW
千家信息网最后更新 2026年11月02日如何进行BeanDefinition的定位,加载和注册

本篇文章给大家分享的是有关如何进行BeanDefinition的定位,加载和注册,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

以XmlWebApplicationContext为例,分析容器初始化过程中一个BeanDefinition的定位,加载和注册过程

  • Resource定位。使用ResourceLoader定位到资源

  • 加载。BeanDefinitionReader解析资源中的bean的定义信息并创建BeanDefinition对象

  • 注册。使用BeanDefinitionRegistry,在容器内部将BeanDefinition对象注册进来

定位

定位的栈

以下是调用refresh()方法定位Resource的栈信息

loadBeanDefinitions:219, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)loadBeanDefinitions:194, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)loadBeanDefinitions:125, XmlWebApplicationContext (org.springframework.web.context.support)loadBeanDefinitions:94, XmlWebApplicationContext (org.springframework.web.context.support)refreshBeanFactory:133, AbstractRefreshableApplicationContext (org.springframework.context.support)obtainFreshBeanFactory:621, AbstractApplicationContext (org.springframework.context.support)refresh:522, AbstractApplicationContext (org.springframework.context.support)...

定位流程

调用BeanDefinitionReader持有的ResourceLoader对象的Resource getResource(String var1);方法获取到Resource

ps:在Applicationcontext的继承体系中,Applicationcontext实现了ResourceLoader,所以容器也是一个ResourceLoader。通常BeanDefinitionReader持有的ResourceLoader对象就是当前使用的容器

loadBeanDefinitions:94, XmlWebApplicationContext (org.springframework.web.context.support)

下面的方法对应此栈,方法实现在XmlWebApplicationContext

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {    // 创建一个XmlBeanDefinitionReader,用于定位Bean定义信息    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);    beanDefinitionReader.setEnvironment(getEnvironment());    // XmlWebApplicationContext的继承体系中实现了ResourceLoader,所以this是一个ResourceLoader    beanDefinitionReader.setResourceLoader(this);    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));    // Allow a subclass to provide custom initialization of the reader,    // then proceed with actually loading the bean definitions.    initBeanDefinitionReader(beanDefinitionReader);    loadBeanDefinitions(beanDefinitionReader);}

上述方法创建了一个BeanDefinitionReader,并将容器作为ResourceLoader传递进去

loadBeanDefinitions:219, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)

下面的方法对应此栈,调用方法的是上一步创建的XmlBeanDefinitionReader对象,方法实现在AbstractBeanDefinitionReader中

public int loadBeanDefinitions(String location, @Nullable Set actualResources) throws BeanDefinitionStoreException {    ResourceLoader resourceLoader = getResourceLoader();    if (resourceLoader == null) {        throw new BeanDefinitionStoreException("...");    }    if (resourceLoader instanceof ResourcePatternResolver) {        try {            // 至此,完成BeanDefinition的Resource的定位。获取到Resource            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);            // BenaDefinition的加载和注册在此方法中            int loadCount = loadBeanDefinitions(resources);            if (actualResources != null) {                for (Resource resource : resources) {                    actualResources.add(resource);                }            }            return loadCount;        }        catch (IOException ex) {            throw new BeanDefinitionStoreException("...", ex);        }    }    else {        // 至此,完成BeanDefinition的Resource的定位。获取到Resource        Resource resource = resourceLoader.getResource(location);        // BenaDefinition的加载和注册均在此方法中        int loadCount = loadBeanDefinitions(resource);        if (actualResources != null) {            actualResources.add(resource);        }        if (logger.isDebugEnabled()) {            logger.debug("...");        }        return loadCount;    }}

加载

加载的栈

// 此方法包含BeanDefinition的加载和注册processBeanDefinition:305, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)parseDefaultElement:196, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)parseBeanDefinitions:175, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)doRegisterBeanDefinitions:148, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)registerBeanDefinitions:98, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)registerBeanDefinitions:507, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)// 此方法包含了BeanDefinition加载的两大步骤(解析xml文件创建Document对象,BeanDefinition加载和注册)doLoadBeanDefinitions:391, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)loadBeanDefinitions:335, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)loadBeanDefinitions:303, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)loadBeanDefinitions:187, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)// 这里包含BeanDefinition的定位,同时也包含BeanDefinition的加载和注册的入口方法loadBeanDefinitions:223, AbstractBeanDefinitionReader (org.springframework.beans.factory.support)...refresh:522, AbstractApplicationContext (org.springframework.context.support)...

加载流程

加载分为两步

  1. 使用XML的解析器获取到Document对象(需要解析xml文件是因为bean的定义信息是在xml文件里写的)

  2. 使用DocumentReader按照Spring定义Bean的规则解析xml文件并创建BeanDefinition对象。创建的BeanDefinition对象会先被BeanDefinitionHolder封装起来

doLoadBeanDefinitions:391, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)

下面的方法对应此栈,方法实现在XmlBeanDefinitionReader中

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {    try {        // 解析xml文件,创建Document对象        Document doc = doLoadDocument(inputSource, resource);        // BeanDefinition的加载和注册        return registerBeanDefinitions(doc, resource);    }    catch (Throwable ex) {        throw ...    }}
parseBeanDefinitions:175, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)

下面的方法对应此栈。获取xml中的根节点,获取根节点下的所有子节点,遍历

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {                if (delegate.isDefaultNamespace(root)) {                        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);                }        }
processBeanDefinition:305, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)

下面的方法对应此栈。方法的调用者DefaultBeanDefinitionDocumentReader是由XmlBeanDefinitionReader创建的

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {    // 至此,完成BeanDefinition的加载。创建BeanDefinition对象并将结果交给BeanDefinitionHolder持有    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);    if (bdHolder != null) {        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);        try {            // BeanDefinition的注册在此方法中            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));    }}

注册

注册的栈

registerBeanDefinition:792, DefaultListableBeanFactory (org.springframework.beans.factory.support)registerBeanDefinition:150, BeanDefinitionReaderUtils (org.springframework.beans.factory.support)processBeanDefinition:310, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)parseDefaultElement:196, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)parseBeanDefinitions:175, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)doRegisterBeanDefinitions:148, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)registerBeanDefinitions:98, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)registerBeanDefinitions:507, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)// 此方法包含了BeanDefinition加载的两大步骤(解析xml文件创建Document对象,BeanDefinition加载和注册)doLoadBeanDefinitions:391, XmlBeanDefinitionReader (org.springframework.beans.factory.xml)...

注册流程

以kv键值对的方式将beanName和BeanDefinition对象put到容器内部的一个map中(类型是ConcurrentHashMap)

processBeanDefinition:310, DefaultBeanDefinitionDocumentReader (org.springframework.beans.factory.xml)

下面的方法对应此栈

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {    // 创建BeanDefinition并将其包装在BeanDefinitionHolder中    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);    if (bdHolder != null) {        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);        try {            // 将BeanDefinition注册到容器中            // 方法的第二个参数是DefaultListableBeanFactory对象            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());        }        catch (BeanDefinitionStoreException ex) {            getReaderContext().error("...", ele, ex);        }        // 发布注册事件        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));    }}
registerBeanDefinition:150, BeanDefinitionReaderUtils (org.springframework.beans.factory.support)

下面的方法对应此栈。这里的BeanDefinitionRegistry的实际类型是DefaultListableBeanFactory

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {    String beanName = definitionHolder.getBeanName();    // 调用BeanDefinitionRegistry(Bean定义信息注册中心)将BeanDefinition以kv形式注册到容器中。k是beanName,v是对象    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());    String[] aliases = definitionHolder.getAliases();    if (aliases != null) {        for (String alias : aliases) {            // 把别名也注册到容器中            registry.registerAlias(beanName, alias);        }    }}
registerBeanDefinition:792, DefaultListableBeanFactory (org.springframework.beans.factory.support)

下面的方法对应此栈。方法实现在DefaultListableBeanFactory,方法由BeanDefinitionRegistry接口定义

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {    if (beanDefinition instanceof AbstractBeanDefinition) {        try {            ((AbstractBeanDefinition) beanDefinition).validate();        }        catch (BeanDefinitionValidationException ex) {            throw ...        }    }    BeanDefinition oldBeanDefinition;    // 先用beanName从容器中获取BeanDefinition    oldBeanDefinition = this.beanDefinitionMap.get(beanName);    // 如果容器中确实已经存在同名BeanDefinition对象,根据之前设置的能否覆盖同名对象进行操作    if (oldBeanDefinition != null) {        // 如果设置的是  不能覆盖同名对象,抛异常        if (!isAllowBeanDefinitionOverriding()) {            throw new ...        }        else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {           ...        }        else if (!beanDefinition.equals(oldBeanDefinition)) {            ...        }        else {            ...        }        // 如果 能覆盖同名对象,将beanDefinition对象put到map中        // 这个map就是容器中BeanDefinition的持有者,        this.beanDefinitionMap.put(beanName, beanDefinition);    }    else {        if (hasBeanCreationStarted()) {            synchronized (this.beanDefinitionMap) {                // 将beanDefinition对象put到map中                this.beanDefinitionMap.put(beanName, beanDefinition);                List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);                updatedDefinitions.addAll(this.beanDefinitionNames);                updatedDefinitions.add(beanName);                this.beanDefinitionNames = updatedDefinitions;                if (this.manualSingletonNames.contains(beanName)) {                    Set updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);                    updatedSingletons.remove(beanName);                    this.manualSingletonNames = updatedSingletons;                }            }        }        else {            // 将beanDefinition对象put到map中            this.beanDefinitionMap.put(beanName, beanDefinition);            this.beanDefinitionNames.add(beanName);            this.manualSingletonNames.remove(beanName);        }        this.frozenBeanDefinitionNames = null;    }    if (oldBeanDefinition != null || containsSingleton(beanName)) {        resetBeanDefinition(beanName);    }}

此方法会将BeanDefinition对象put到map中

以上就是如何进行BeanDefinition的定位,加载和注册,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

0