美文网首页
Spring5IOC容器解析——BeanDefinition的注

Spring5IOC容器解析——BeanDefinition的注

作者: 小波同学 | 来源:发表于2020-06-08 02:47 被阅读0次

前言

在上一篇文章解析BeanDefinition
对配置文件解析完成后,获取的beanDefiniton已经可以进行使用了,剩下的唯一工作就是注册了,也就是processBeanDefinition方法中的BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())代码的解析了。

BeanDefinitionRegistry

该类的作用主要是向注册表中注册 BeanDefinition 实例,完成 注册的过程。
它的接口定义如下:

public interface BeanDefinitionRegistry extends AliasRegistry {

    /**
     * 往注册表中注册一个新的 BeanDefinition 实例
     * Register a new bean definition with this registry.
     * Must support RootBeanDefinition and ChildBeanDefinition.
     * @param beanName the name of the bean instance to register
     * @param beanDefinition definition of the bean instance to register
     * @throws BeanDefinitionStoreException if the BeanDefinition is invalid
     * @throws BeanDefinitionOverrideException if there is already a BeanDefinition
     * for the specified bean name and we are not allowed to override it
     * @see GenericBeanDefinition
     * @see RootBeanDefinition
     * @see ChildBeanDefinition
     */
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException;

    /**
     * 移除注册表中已注册的 BeanDefinition 实例
     * Remove the BeanDefinition for the given name.
     * @param beanName the name of the bean instance to register
     * @throws NoSuchBeanDefinitionException if there is no such bean definition
     */
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * 从注册中取得指定的 BeanDefinition 实例
     * Return the BeanDefinition for the given bean name.
     * @param beanName name of the bean to find a definition for
     * @return the BeanDefinition for the given name (never {@code null})
     * @throws NoSuchBeanDefinitionException if there is no such bean definition
     */
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * 判断 BeanDefinition 实例是否在注册表中(是否注册)
     * Check if this registry contains a bean definition with the given name.
     * @param beanName the name of the bean to look for
     * @return if this registry contains a bean definition with the given name
     */
    boolean containsBeanDefinition(String beanName);

    /**
     * 取得注册表中所有 BeanDefinition 实例的 beanName(标识)
     * Return the names of all beans defined in this registry.
     * @return the names of all beans defined in this registry,
     * or an empty array if none defined
     */
    String[] getBeanDefinitionNames();

    /**
     * 返回注册表中 BeanDefinition 实例的数量
     * Return the number of beans defined in the registry.
     * @return the number of beans defined in the registry
     */
    int getBeanDefinitionCount();

    /**
     * beanName(标识)是否被占用
     * Determine whether the given bean name is already in use within this registry,
     * i.e. whether there is a local bean or alias registered under this name.
     * @param beanName the name to check
     * @return whether the given bean name is already in use
     */
    boolean isBeanNameInUse(String beanName);
}

再来看BeanDefinitionRegistry的继承关系,DefaultListableBeanFactory赫然在列:


DefaultListableBeanFactory

该类是 BeanDefinitionRegistry 接口的基本实现类,但同时也实现其他了接口的功能,这里只探究下其关于注册 BeanDefinition 实例的相关方法 。

首先来看它的成员变量:

// 关键-> 注册表,由 BeanDefinition 的标识 (beanName) 与其实例组成
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

// 标识(beanName)集合
/** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

现在进入DefaultBeanDefinitionDocumentReader类的processBeanDefinition方法

/**
 * Process the given bean element, parsing the bean definition
 * and registering it with the registry.
 * 解析BeanDefinition资源
 */
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
    //对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // Register the final decorated instance.
            //向Spring IOC容器注册解析得到的BeanDefinition,这是BeanDefinition向IOC容器注册的入口
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                    bdHolder.getBeanName() + "'", ele, ex);
        }
        // Send registration event.
        // 在完成BeanDefinition注册之后,往容器发送注册完成的事件
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

再来看 BeanDefinitionReaderUtils 的 registerBeanDefinition 方法。该方法的主要作用是调用注册器(DefaultListableBeanFactory)完成注册过程。

/**
 * Register the given bean definition with the given bean factory.
 * @param definitionHolder the bean definition including name and aliases
 * @param registry the bean factory to register with
 * @throws BeanDefinitionStoreException if registration failed
 */
public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {

    // Register bean definition under primary name.
    // 使用beanName做唯一标识注册
    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);
        }
    }
}

从上面的代码可以看出,解析的beanDefinition都会被注册到BeanDefinitionRegistry类型的实例中,而对于beanDefinition的注册分成了两部分:通过beanName的注册以及通过别名的注册。

1、通过beanName注册BeanDefinition

对于beanDefinition的注册,是将beanDefinition直接放入了map中,以beanName为key。但不仅仅如此,代码如下:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    /** Resolver to use for checking if a bean definition is an autowire candidate. */
    private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();

    /** Map from dependency type to corresponding autowired value. */
    private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

    // 关键-> 注册表,由 BeanDefinition 的标识 (beanName) 与其实例组成
    /** Map of bean definition objects, keyed by bean name. */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

    /** Map from bean name to merged BeanDefinitionHolder. */
    private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);

    /** Map of singleton and non-singleton bean names, keyed by dependency type. */
    private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

    /** Map of singleton-only bean names, keyed by dependency type. */
    private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

    // 标识(beanName)集合
    /** List of bean definition names, in registration order. */
    private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

    /** List of names of manually registered singletons, in registration order. */
    private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);

    /** Cached array of bean definition names in case of frozen configuration. */
    @Nullable
    private volatile String[] frozenBeanDefinitionNames;

    /** Whether bean definition metadata may be cached for all beans. */
    private volatile boolean configurationFrozen = false;

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
        // 校验 beanName 与 beanDefinition 非空
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");

        /**
         * 1、校验 BeanDefinition
         * 注册前的最后一次校验,这里的校验不同于之前的XML文件校验,
         * 主要是对于AbstractBeanDefinition属性中的lookup-method属性和replaced-method属性对应的重写方法是否存在并且合法,
         * 校验methodOverrides是否与工厂方法并存或者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、看看beanName是否已经存在容器里,存在则表明已经被注册过
        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()) {
                    // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                    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 + "]");
                }
            }
            else {
                // 其它,打印 debug 日志
                if (logger.isTraceEnabled()) {
                    logger.trace("Overriding bean definition for bean '" + beanName +
                            "' with an equivalent definition: replacing [" + existingDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            // 允许覆盖,直接覆盖原有的 BeanDefinition 到 beanDefinit 大专栏  注册BeanDefinitions-下ionMap 中。
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        //4、如果未存在
        else {
            // 检测创建 Bean 阶段是否已经开启,如果开启了则需要对 beanDefinitionMap 进行并发控制
            if (hasBeanCreationStarted()) {
                // beanDefinitionMap 为全局变量,避免并发情况
                // Cannot modify startup-time collection elements anymore (for stable iteration)
                synchronized (this.beanDefinitionMap) {
                    // 添加BeanDefinition 到 beanDefinitionMap 中。
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    // 添加 beanName 到 beanDefinitionNames 中
                    List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    // 从 manualSingletonNames 移除 beanName
                    removeManualSingletonName(beanName);
                }
            }
            else {
                // Still in startup registration phase
                // 添加 BeanDefinition 到 beanDefinitionMap 中。
                this.beanDefinitionMap.put(beanName, beanDefinition);
                // 添加 beanName 到 beanDefinitionNames 中
                this.beanDefinitionNames.add(beanName);
                // 从 manualSingletonNames 移除 beanName
                removeManualSingletonName(beanName);
            }
            //将注册期间被冻结的BeanDefinition的名字列表清除掉
            this.frozenBeanDefinitionNames = null;
        }
        // 5、重新设置 beanName 对应的缓存
        //检查是否有同名的BeanDefinition已经在IOC容器中注册
        if (existingDefinition != null || containsSingleton(beanName)) {
            //尝试重置所有已经注册过的BeanDefinition的缓存,包括BeanDefinition
            //的父类以及合并的beanDefinition的缓存,所谓的合并BeanDefinition
            //指的的有parent属性的beandefinition,该BeanDefinition会把parent的
            //BeanDefinition属性合并在一块
            resetBeanDefinition(beanName);
        }
        else if (isConfigurationFrozen()) {
            clearByTypeCache();
        }
    }
}

上面的代码中我们看到,在对于bean的注册处理方式上,主要进行了几个步骤:

  • 1、对AbstractBeanDefinition的校验。在解析XML文件的时候我们提过校验,但是此校验非彼校验,之前的校验是针对XML格式的校验,而此时的校验是针对AbstractBeanDefinition的methodOverrides属性的。
  • 2、对beanName已经注册的情况的处理。如果设置了不允许bean的覆盖,则需要抛出异常,否则直接覆盖。
  • 3、加入map缓存。
  • 4、清楚解析之前留下的对应beanName的缓存。

2、通过别名注册BeanDefinition

在理解了注册bean的原理后,理解注册别名的原理就容易多了。

先看别名注册接口AliasRegistry
public interface AliasRegistry {

    /**
     * 注册表中给name注册一个别名alias
     * Given a name, register an alias for it.
     * @param name the canonical name
     * @param alias the alias to be registered
     * @throws IllegalStateException if the alias is already in use
     * and may not be overridden
     */
    void registerAlias(String name, String alias);

    /**
     * 移除注册表中的别名alias
     * Remove the specified alias from this registry.
     * @param alias the alias to remove
     * @throws IllegalStateException if no such alias was found
     */
    void removeAlias(String alias);

    /**
     * 校验注册表中是否存在别名name
     * Determine whether the given name is defined as an alias
     * (as opposed to the name of an actually registered component).
     * @param name the name to check
     * @return whether the given name is an alias
     */
    boolean isAlias(String name);

    /**
     * 在注册表中获取给定那么的所有别名信息
     * Return the aliases for the given name, if defined.
     * @param name the name to check for aliases
     * @return the aliases, or an empty array if none
     */
    String[] getAliases(String name);

}
接着跟进registry.registerAlias(beanName, alias)
public class SimpleAliasRegistry implements AliasRegistry {

    //别名-规范名称的映射MAP,用于存储注册信息(内存注册表)
    /** Map from alias to canonical name. */
    private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);

    //注册表中注册别名
    @Override
    public void registerAlias(String name, String alias) {
        Assert.hasText(name, "'name' must not be empty");
        Assert.hasText(alias, "'alias' must not be empty");
        //锁注册表
        //因为CurrentHashMap只有put和remove是线程安全的
        //此处要包装对CurrentHashMap的复合操作线程安全
        synchronized (this.aliasMap) {
            // 如果beanName与alias相同的话不记录alias,并删除对应的alias
            if (alias.equals(name)) {
                //如果别名与名字相同,则在Map中移除
                this.aliasMap.remove(alias);
                if (logger.isDebugEnabled()) {
                    logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
                }
            }
            else {
                //获取当前别名在注册表中的规范名称
                String registeredName = this.aliasMap.get(alias);
                if (registeredName != null) {
                    //规范名称存在,不需要注册,返回
                    if (registeredName.equals(name)) {
                        // An existing alias - no need to re-register
                        return;
                    }
                    //判断是否允许重写注册
                    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);
                // 注册表注册别名与规范名称的映射
                this.aliasMap.put(alias, name);
                if (logger.isTraceEnabled()) {
                    logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
                }
            }
        }
    }
}

由以上代码中可以得知注册alias的步骤如下:

  • 1、beanName与alias相同情况处理。若alias和beanName名称相同则不需要处理并删除原有的alias。
  • 2、alias覆盖处理。若aliasName已经使用并已经指向了另一beanName则需要用户的设置进行处理。
  • 3、alias循环检查。当A -> B存在时,若再次出现 A -> C -> B时候则会抛出异常。
  • 4、注册alias。
SimpleAliasRegistry的其他方法
public class SimpleAliasRegistry implements AliasRegistry {

    /** Logger available to subclasses. */
    protected final Log logger = LogFactory.getLog(getClass());

    //别名-规范名称的映射MAP,用于存储注册信息(内存注册表)
    /** Map from alias to canonical name. */
    private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);


    //注册表中注册别名
    @Override
    public void registerAlias(String name, String alias) {
        Assert.hasText(name, "'name' must not be empty");
        Assert.hasText(alias, "'alias' must not be empty");
        //锁注册表
        //因为CurrentHashMap只有put和remove是线程安全的
        //此处要包装对CurrentHashMap的复合操作线程安全
        synchronized (this.aliasMap) {
            // 如果beanName与alias相同的话不记录alias,并删除对应的alias
            if (alias.equals(name)) {
                //如果别名与名字相同,则在Map中移除
                this.aliasMap.remove(alias);
                if (logger.isDebugEnabled()) {
                    logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
                }
            }
            else {
                //获取当前别名在注册表中的规范名称
                String registeredName = this.aliasMap.get(alias);
                if (registeredName != null) {
                    //规范名称存在,不需要注册,返回
                    if (registeredName.equals(name)) {
                        // An existing alias - no need to re-register
                        return;
                    }
                    //判断是否允许重写注册
                    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);
                // 注册表注册别名与规范名称的映射
                this.aliasMap.put(alias, name);
                if (logger.isTraceEnabled()) {
                    logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
                }
            }
        }
    }

    /**
     * 是否允许重写注册表别名信息,默认true
     * Determine whether alias overriding is allowed.
     * <p>Default is {@code true}.
     */
    protected boolean allowAliasOverriding() {
        return true;
    }

    /**
     * 校验给定的name-alias映射是否已在注册表aliasMap中
     * Determine whether the given name has the given alias registered.
     * @param name the name to check
     * @param alias the alias to look for
     * @since 4.2.1
     */
    public boolean hasAlias(String name, String alias) {
        //获取注册表中单映射的规范名称name
        String registeredName = this.aliasMap.get(alias);
        return ObjectUtils.nullSafeEquals(registeredName, name) || (registeredName != null
                && hasAlias(name, registeredName));
    }

    /**
     *  移除别名,在注册表aliasMap中
     * @param alias the alias to remove
     */
    @Override
    public void removeAlias(String alias) {
        synchronized (this.aliasMap) {
            String name = this.aliasMap.remove(alias);
            if (name == null) {
                throw new IllegalStateException("No alias '" + alias + "' registered");
            }
        }
    }

    //校验是否包含给定的别名,在注册表中
    @Override
    public boolean isAlias(String name) {
        return this.aliasMap.containsKey(name);
    }

    // 在注册表获取给定规范名称的所有别名信息
    @Override
    public String[] getAliases(String name) {
        List<String> result = new ArrayList<>();
        synchronized (this.aliasMap) {
            retrieveAliases(name, result);
        }
        return StringUtils.toStringArray(result);
    }

    /**
     * Transitively retrieve all aliases for the given name.
     * @param name the target name to find aliases for
     * @param result the resulting aliases list
     */
    private void retrieveAliases(String name, List<String> result) {
        this.aliasMap.forEach((alias, registeredName) -> {
            //判断当前别名的规范名称是否为要查询的
            if (registeredName.equals(name)) {
                result.add(alias);
                //递归查询循环引用的别名
                retrieveAliases(alias, result);
            }
        });
    }

    /**
     * Resolve all alias target names and aliases registered in this
     * registry, applying the given {@link StringValueResolver} to them.
     * <p>The value resolver may for example resolve placeholders
     * in target bean names and even in alias names.
     * @param valueResolver the StringValueResolver to apply
     */
    public void resolveAliases(StringValueResolver valueResolver) {
        Assert.notNull(valueResolver, "StringValueResolver must not be null");
        synchronized (this.aliasMap) {
            Map<String, String> aliasCopy = new HashMap<>(this.aliasMap);
            aliasCopy.forEach((alias, registeredName) -> {
                String resolvedAlias = valueResolver.resolveStringValue(alias);
                String resolvedName = valueResolver.resolveStringValue(registeredName);
                if (resolvedAlias == null || resolvedName == null || resolvedAlias.equals(resolvedName)) {
                    this.aliasMap.remove(alias);
                }
                else if (!resolvedAlias.equals(alias)) {
                    String existingName = this.aliasMap.get(resolvedAlias);
                    if (existingName != null) {
                        if (existingName.equals(resolvedName)) {
                            // Pointing to existing alias - just remove placeholder
                            this.aliasMap.remove(alias);
                            return;
                        }
                        throw new IllegalStateException(
                                "Cannot register resolved alias '" + resolvedAlias + "' (original: '" + alias +
                                "') for name '" + resolvedName + "': It is already registered for name '" +
                                registeredName + "'.");
                    }
                    checkForAliasCircle(resolvedName, resolvedAlias);
                    this.aliasMap.remove(alias);
                    this.aliasMap.put(resolvedAlias, resolvedName);
                }
                else if (!registeredName.equals(resolvedName)) {
                    this.aliasMap.put(alias, resolvedName);
                }
            });
        }
    }

    /**
     * 校验给定的名称是否指向别名,不指向异常抛出
     * Check whether the given name points back to the given alias as an alias
     * in the other direction already, catching a circular reference upfront
     * and throwing a corresponding IllegalStateException.
     * @param name the candidate name
     * @param alias the candidate alias
     * @see #registerAlias
     * @see #hasAlias
     */
    protected void checkForAliasCircle(String name, String alias) {
        if (hasAlias(alias, name)) {
            throw new IllegalStateException("Cannot register alias '" + alias +
                    "' for name '" + name + "': Circular reference - '" +
                    name + "' is a direct or indirect alias for '" + alias + "' already");
        }
    }

    /**
     * 根据给定的别名获取规范名称
     * Determine the raw name, resolving aliases to canonical names.
     * @param name the user-specified name
     * @return the transformed name
     */
    public String canonicalName(String name) {
        String canonicalName = name;
        // Handle aliasing...
        String resolvedName;
        do {
            //获取给定别名的规范名称,获取到跳出循环
            resolvedName = this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        }
        while (resolvedName != null);
        return canonicalName;
    }

}

SimpleBeanDefinitionRegistry 为BeanDefinitionRegistry的默认实现,同时继承AliasRegistry的默认实现SimpleAliasRegistry,所以它总共维护了两个注册表aliasMap(别名注册表)与beanDefinitionMap(bean描述注册表),到此AliasRegistry接口功能的主要实现以及扩展接口的主要实现通过源码已清晰展示

参考:
https://www.cnblogs.com/monkey0307/p/8509701.html

https://www.cnblogs.com/warehouse/p/9380473.html

https://www.cnblogs.com/moxiaotao/p/9349549.html

https://www.cnblogs.com/loongk/p/12297193.html

https://blog.csdn.net/whoyou223/article/details/78205803

相关文章

网友评论

      本文标题:Spring5IOC容器解析——BeanDefinition的注

      本文链接:https://www.haomeiwen.com/subject/xfuktktx.html