美文网首页Spring
[Spring]BeanDefinitionRegistry-B

[Spring]BeanDefinitionRegistry-B

作者: AbstractCulture | 来源:发表于2020-12-30 16:33 被阅读0次

    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
    • SimpleBeanDefinitionRegistry:BeanDefinitionRegistry较为简单的实现,仅提供注册能力,不提供工厂级别的能力,可作为简单的例子提供给读者做test使用.
    • DefaultListableBeanFactory:Spring最早可以独立运行的工厂类,不仅有容器注册功能,还是一个功能健全的Bean工厂。
    • GenericApplicationContext:Spring通用上下文,需要较多的自定义实现。

    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.这里梳理一下主要的逻辑

      1. 判断是否为AbstractBeanDefinition的实例,如果是,校验该BeanDefinition是否有声明需要overrides的方法,如果有,创建代理类进行代理。
      1. beanDefinitionMap中尝试获取该beanName的BeanDefinition.
      1. 如果beanDefinitionMap已经有了,检测是否允许BeanDefinition覆盖。如果允许,则用put进行更新操作.
      1. 如果从beanDefinitionMap获取不到,证明是新的BeanDefinition,查看工厂的bean是否进入已创建的阶段了,如果是,则证明是动态注册bean的方式.使用synchronizedbeanDefinitionMap上锁,让进行put操作,再依次更新beanDefinitionNames和从manualSingletonNames(手动注册单例的名称列表,按注册顺序。)中将该beanName移除
      1. 如果该BeanDefinition已存在,并且在单例缓存中,那么进行resetBeanDefinition,这是一个递归的过程,主要的工作是:清除合并的BeanDefinition缓存,从单例缓存中将该BeanName移除,通知处理器进行reset操作.
        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

    总结

    • BeanDefinition的注册具体表现为往DefaultListableBeanFactory中的beanDefinitionMap中添加一个BeanDefinition.
    • BeanDefinitionReader将注册功能委托给了DefaultListableBeanFactory进行注册.该注册器在初始化的时候进行了构造注入.
    • 在注册期间,Spring会校验是否允许BeanDefinition覆盖.
    • Spring支持在工厂创建Bean实例后进行动态注册BeanDefinition.

    相关文章

      网友评论

        本文标题:[Spring]BeanDefinitionRegistry-B

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