Spring

[Spring]BeanDefinitionRegistry-B

2020-12-30  本文已影响0人  AbstractCulture

BeanDefinitionRegistry

Spring中BeanDefinition的注册接口,常见的实现有DefaultListableBeanFactoryGenericApplicationContext。看看它的接口清单:

public interface BeanDefinitionRegistry extends AliasRegistry {
    // 往注册表中注册一个BeanDefinition实例
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException;
    // 从注册表中移除带有该BeanName的BeanDefinition
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    // 通过beanName从注册表中获取BeanDefinition
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    // 判断当前是否已经注册了该beanName的BeanDefinition
    boolean containsBeanDefinition(String beanName);
    // 获取当前注册的所有BeanDefinition的Name
    String[] getBeanDefinitionNames();
    // 获取当前已注册的BeanDefinition数量
    int getBeanDefinitionCount();
    // beanName(标识)是否被占用
    boolean isBeanNameInUse(String beanName);
}

UML

UML

DefaultListableBeanFactory的注册功能

前程回顾

上文中提到,BeanDefinitionReader在调用完BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);后,会调用BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());方法对该BeanDefinition进行注册.

DefaultListableBeanFactory会将注册后的BeanDefinition放到一个ConcurrentHashMap的Map中进行存储,Key为beanName,Value为BeanDefinition。

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

注册的入口

这里传入了两个参数,bdHolder为BeanDefinition的包装器,getReaderContext().getRegistry()为DefaultListableBeanFactory。为什么是DefaultListableBeanFactory?因为Spring在实例化XmlBeanDefinitionReader的时候将容器本身作为参数进行了传递,这在设计模式上也可以称为委托。

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

DefaultListableBeanFactory的多职能

DefaultListableBeanFactory本身不仅作为工厂使用,而且还可以用作注册器,资源加载器。

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        // 这里就是委托的体现,将DefaultListableBeanFactory作为构造参数传入了XmlBeanDefinitionReader中
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        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);
    }

进入到构造函数中,发现DefaultListableBeanFactory在这里已经充当了registry的职能了.

    public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
        super(registry);
    }
注册器实例

注册BeanDefinition-注册name和aliases

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

        // Register bean definition under primary name.
        // 向容器注入BeanDefinition的名称和BeanDefinition本身
        String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // Register aliases for bean name, if any.
        // 如果该BeanDefinition存在别名,再对别名进行注册
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }

DefaultListableBeanFactory#registerBeanDefinition

注意,这里已经到达了DefaultLististableBeanFactory的registerBeanDefinition中了,上面的registry指向的是DefaultLististableBeanFactory.这里梳理一下主要的逻辑

    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是否为AbstractBeanDefinition的实例
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                // 校验look up 和 replace method 是否存在并且参数合法,如果存在,对该BeanDefinition进一步处理
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
        // 从注册表中获取该BeanDefinition实例
        BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) {
            // 是否允许BeanDefinition覆盖,容器配置
            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 + "]");
                }
            }
            // 将beanName作为key,BeanDefinition作为value,放到容器map中
            this.beanDefinitionMap.put(beanName, beanDefinition);
        }
        else {
            // 是否开始创建bean实例,如果已经有该实例,那么本次为动态的形式
            if (hasBeanCreationStarted()) {
                // Cannot modify startup-time collection elements anymore (for stable iteration)
                // 锁住注册表
                synchronized (this.beanDefinitionMap) {
                    // 更新beanDefinition
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    // 创建一个长度为beanDefinitionNames+1的列表
                    List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                    // 先将存量的beanDefinitionName存储
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    // 再存储增量的beanName,顺序存储
                    updatedDefinitions.add(beanName);
                    // 更新整个BeanDefinitionNames
                    this.beanDefinitionNames = updatedDefinitions;
                    // 从单例BeanName列表中移除该beanName,如果this.manualSingletonNames中contains该beanName,执行remove操作
                    removeManualSingletonName(beanName);
                }
            }
            else {
                // Still in startup registration phase
                // 启动阶段
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                removeManualSingletonName(beanName);
            }
            // 将注册期间冻结的beanName列表清除,一个volatile修饰的String数组,Spring内存优化操作
            this.frozenBeanDefinitionNames = null;
        }
        // 检测是否存在该BeanDefinition且存在于IOC中
        if (existingDefinition != null || containsSingleton(beanName)) {
            // 重置注册的BeanDefinition缓存
            // 包括BeanDefinition的父类以及合并的BeanDefinition缓存,即mergeBeanDefinition
            // Spring会把有parent属性的Bean属性进行合并
            resetBeanDefinition(beanName);
        }
        else if (isConfigurationFrozen()) {
            clearByTypeCache();
        }
    }

DefaultListableBeanFactory#resetBeanDefinition

    protected void resetBeanDefinition(String beanName) {
        // Remove the merged bean definition for the given bean, if already created.
        // 如果该beanName发生过merge操作,remove已经合并出的beanDefinition
        clearMergedBeanDefinition(beanName);

        // Remove corresponding bean from singleton cache, if any. Shouldn't usually
        // be necessary, rather just meant for overriding a context's default beans
        // (e.g. the default StaticMessageSource in a StaticApplicationContext).
        // 从单例缓存中remove该beanName
        destroySingleton(beanName);

        // Notify all post-processors that the specified bean definition has been reset.
        // 通知MergedBeanDefinitionPostProcessor,这个特殊的beanDefinition已经进行了重置
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            if (processor instanceof MergedBeanDefinitionPostProcessor) {
                ((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
            }
        }

        // Reset all bean definitions that have the given bean as parent (recursively).
        // 找出容器中与当前beanName不相同的bd,查看paretName是否跟当前beanName相同。
        // 即父bean被清除了,子bean也应该要重置
        for (String bdName : this.beanDefinitionNames) {
            if (!beanName.equals(bdName)) {
                BeanDefinition bd = this.beanDefinitionMap.get(bdName);
                // Ensure bd is non-null due to potential concurrent modification
                // of the beanDefinitionMap.
                if (bd != null && beanName.equals(bd.getParentName())) {
                    // 递归调用,如果该bean还有子bean,继续进行清除
                    resetBeanDefinition(bdName);
                }
            }
        }
    }

流程图

Registry

总结

上一篇 下一篇

猜你喜欢

热点阅读