• 5. Spring源码篇之BeanDefinition


    简介

    在spring中BeanDefinition是一个接口,下面也有很多的实现类

    大致如下

    BeanDefinition
        AbstractBeanDefinition
            RootBeanDefinition              最终每个BeanDefinition都是一个 RootBeanDefinition
            ChildBeanDefinition             现在不用了废弃,现在使用的都是 GenericBeanDefinition
            GenericBeanDefinition           我们定义的一般都是 GenericBeanDefinition
            ScannedGenericBeanDefinition    是GenericBeanDefinition的一个子类,表示是通过scanner扫描出来的Bean
            AnnotatedGenericBeanDefinition  是GenericBeanDefinition的一个子类,表示是通过reader注册的Bean
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    属性

    beanClass           bean对应的类,是一个object类型,在还没有实例化单例Bean的时候放入的是类全限定名,实例化后就是class
    scope               单例 多例等
    abstractFlag        标志无法实例化
    lazyInit            懒加载
    autowireMode        AUTOWIRE_NO,AUTOWIRE_BY_NAME,AUTOWIRE_BY_TYPE,AUTOWIRE_CONSTRUCTOR,AUTOWIRE_AUTODETECT
    dependsOn           依赖于其它bean,其它bean会先初始化
    instanceSupplier    对象来源于Supplier
    factoryBeanName     factoryBean的名字
    factoryMethodName   @Bean的时候会有值
    initMethodName      初始化方法
    destroyMethodName   销毁方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    mergedBeanDefinitions

    在spring中并没有该类的定义,但却十分重要

    private final Map mergedBeanDefinitions = new ConcurrentHashMap<>(256);

    一般来说我们的bean都是GenericBeanDefinition,其实也是RootBeanDefinition,但是在xml方式下,可以设置一个BeanDefinition为abstract的,可供其它bean继承它,从而得到自己没有定义的属性

    例如

    spring.xml

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
    	   https://www.springframework.org/schema/beans/spring-beans.xsd
    	   http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"
    >
        <bean id="abs" scope="prototype" abstract="true"/>
        <bean id="userBean" class="com.shura.beans.UserBean" parent="abs"/>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    使用xml方式

    public class Application {
    	public static void main(String[] args) {
    		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    		System.out.println(context.getBean(UserBean.class));
    		System.out.println(context.getBean(UserBean.class));
    		System.out.println(context.getBean(UserBean.class));
    
    	}
    }
    
    输出
    com.shura.beans.UserBean@7506e922
    com.shura.beans.UserBean@4ee285c6
    com.shura.beans.UserBean@621be5d1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    从上面例子可以看出,定义了一个abs的抽象 BeanDefinition userBean继承了它,从而获得了多例属性

    那么在注册bean的时候就势必要找出父BeanDefinition,继承属性,于是就有了mergedBeanDefinitions

    在实例化单例Bean的时候就有这一步骤

    方法

    org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

    RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

    下面是简化的源码

    protected RootBeanDefinition getMergedBeanDefinition(
    			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
    			throws BeanDefinitionStoreException {
    
        synchronized (this.mergedBeanDefinitions) {
            RootBeanDefinition mbd = null;
            RootBeanDefinition previous = null;
            if (containingBd == null) {
                mbd = this.mergedBeanDefinitions.get(beanName);
            }
    
            // 如果合并过就跳过
            if (mbd == null || mbd.stale) {
                previous = mbd;
                // 是否有parent,大部分都是进入该分支,如果进入该分支,那么本身的BeanDefinition就是RootBeanDefinition
                if (bd.getParentName() == null) {
                    if (bd instanceof RootBeanDefinition) {
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    } else {
                        mbd = new RootBeanDefinition(bd);
                    }
                } else {
                    // 进入这里表示有父BeanDefinition parent != null
                    BeanDefinition pbd;
                    try {
                        String parentBeanName = transformedBeanName(bd.getParentName());
                        if (!beanName.equals(parentBeanName)) {
                            // 寻找父BeanDefinition的父BeanDefinition,知道找不到
                            pbd = getMergedBeanDefinition(parentBeanName);
                        } else {
                            // 抛出异常
                            BeanFactory parent = getParentBeanFactory();
                            if (parent instanceof ConfigurableBeanFactory) {
                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                            } else {
                                throw new NoSuchBeanDefinitionException(parentBeanName,
                                        "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                                "': cannot be resolved without a ConfigurableBeanFactory parent");
                            }
                        }
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                    }
    
                    // 覆盖属性,得到一个新的RootBeanDefinition
                    mbd = new RootBeanDefinition(pbd);
                    mbd.overrideFrom(bd);
                }
    
                if (!StringUtils.hasLength(mbd.getScope())) {
                    // 默认单例
                    mbd.setScope(SCOPE_SINGLETON);
                }
                
                if (containingBd == null && isCacheBeanMetadata()) {
                    // 缓存起来
                    this.mergedBeanDefinitions.put(beanName, mbd);
                }
            }
            if (previous != null) {
                // copy属性
                copyRelevantMergedBeanDefinitionCaches(previous, mbd);
            }
            return mbd;
        }
    }
    
    • 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

    上面就是merge的逻辑,大致就是,如果有父BeanDefinition就合并属性得到一个新的RootBeanDefinition,返回

    本文主要介绍了BeanDefinition以及合并的过程,下一节介绍FactoryBean


    欢迎关注,学习不迷路!

  • 相关阅读:
    使用flow捕获js错误提高代码质量
    java毕业设计城市出行行程智能推荐系统Mybatis+系统+数据库+调试部署
    OS的Alarm定时器调度机制
    FluentCRM 2.6.0:更多功能、集成改进等等!
    口袋参谋:淘宝卖家必备的市场调查分析工具!
    【基于pyAudioKits的Python音频信号处理(二)】数字音频信号的表示
    计算机毕业设计SSM爱行无忧旅游票务管理系统【附源码数据库】
    好饭不怕晚,Google基于人工智能AI大语言对话模型Bard测试和API调用(Python3.10)
    LVGL_基础控件Button
    TCP练习
  • 原文地址:https://blog.csdn.net/weixin_44412085/article/details/134470124