• 从设计模式理解Spring原理之注册器模式


    博客主页:JavaProfessional
    一个专注于Java的博主,致力于使用通俗易懂的语句讲解内容,期待您的关注!

    前言

    读完本章你将获得:

    1. 理解SpringBean注册的过程
    2. 学习注册器模式
    3. 从设计模式出发理解Spring的精妙之处。

    第0步:学习注册器模式

    注册器模式是一种常见的设计模式,主要是将多个实例注册到一个统一的注册器中,然后通过方法直接去调用需要的实例,是不是感觉很像IOC容器呢?
    注册器模式

    第1步:从IOC中获取第一个JavaBean

    点击这里

    第2步:SpringIOC中的注册器模式分析

    SpringIOC中有如下几个概念:

    1. 我们最为熟悉的当然是JavaBean
    2. 我们不接触源码就不知道的概念:BeanDefinition
    3. 核心概念BeanFactory,一个非常重要的IOC容器

    我们今天想要讲解的就和这个比较陌生的概念BeanDefinition有关。

    什么是BeanDefinition?

    Spring中每一个被扫到的bean都会生成一个BeanDefinition,包含bean的全部信息,如该bean的class类型、作用域、是否懒加载、初始化方法、销毁方法等等,其目的是为了防止重复解析导致效率变得低下。

    BeanDefinitionRegistry

    BeanDefinitionRegistry是一个接口,它定义了BeanDefinition的注册、移除、查询等一系列操作。我们先看看BeanDefinitionRegistry的体系结构吧
    在这里插入图片描述
    我们发现Spring的几个概念都实现了BeanDefinitionRegistry,也就是说GenericApplicationContext、DefaultListBeanFactory都有自己的注册方式。我们一起来看看DefaultListBeanFactory是如何实现BeanDefinitionRegistry的吧。

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

    首先看到DefaultListBeanFactory中保存BeanDefinition的方式是使用了Map。下面是注册的具体实现

    @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");
    
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }
    
        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 {
            if (hasBeanCreationStarted()) {
                // Cannot modify startup-time collection elements anymore (for stable iteration)
                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 {
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                removeManualSingletonName(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }
    
        if (existingDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }
        else if (isConfigurationFrozen()) {
            clearByTypeCache();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    好文推荐

    1. 通俗易懂JVM
    2. 为什么Spring中的IOC(控制反转)能够降低耦合性(解耦)?
    3. 效率翻倍,这些idea的逆天功能你知道吗?
  • 相关阅读:
    input输入多行文本:删除“首先 其次 此外 总的来说”
    利用反射对修饰符为final的成员变量进行修改
    浅析数据采集工具Flume
    基于Java健身房管理系统
    k8s 服务升级为啥 pod 会部署到我们不期望的节点上??看来你还不懂污点和容忍度
    Linux基础知识——(2)vim编辑器
    special net 出Lef
    大数据面试题
    蚁群优化算法解决TSP问题(Matlab代码实现)
    支撑全产业AI,需要怎样的算力服务?
  • 原文地址:https://blog.csdn.net/tinpo_123/article/details/125473790