BeanDefinition 合并

Stella981
• 阅读 629

BeanDefinition 的合并

  • 1.BeanDefinition 有父子关系,有个属性叫parentName,通过parentName可以设置BeanDefinition的父子关系

  • 2.为什么要设置BeanDefinition的父子关系,因为子类可以继承父类的属性,抽出共性,跟java的继承有点像

  • 3.BeanDefinition 的合并过程就是将父子关系的 BeanDefinition 属性合并起来,如果有相同的就使用子类的属性值 例子:

      AnnotationConfigApplicationContext applicationContext
                   = new AnnotationConfigApplicationContext(springConfiguration.class);
           //父 RootBeanDefinition        
           RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
           rootBeanDefinition.setScope(AbstractBeanDefinition.SCOPE_DEFAULT);
           rootBeanDefinition.getPropertyValues().add("name","xiaoming");
           applicationContext.registerBeanDefinition("parent",rootBeanDefinition);
       
       //子 ChildBeanDefinition ,会继承使用父类已有的属性值,但是如果属性值冲突,不一样
       //那么合并过程中就会使用子类的
           ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("parent");
           childBeanDefinition.setBeanClass(A.class);
           childBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);
          
    复制代码
    

    什么时候做合并

    在初始化bean工厂的过程中调用: PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors->DefaultListableBeanFactory.getBeanNamesForType

  • DefaultListableBeanFactory.getBeanNamesForType

    public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) { //....... return doGetBeanNamesForType //...... } 复制代码

  • DefaultListableBeanFactory#doGetBeanNamesForType

    private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) { List result = new ArrayList<>(); // 遍历所有的 beanDefinitionNames for (String beanName : this.beanDefinitionNames) { // Only consider bean as eligible if the bean name // is not defined as alias for some other bean. if (!isAlias(beanName)) { try { //获取合并的bd RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); //..... } 复制代码

  • AbstractBeanFactory#getMergedLocalBeanDefinition

    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
        // 先尝试从缓存获取bd(就是一个map)
        RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
        if (mbd != null) {
            return mbd;
        }
        //合并bd
        return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    }
    

    复制代码

  • AbstractBeanFactory#getMergedBeanDefinition

    protected RootBeanDefinition getMergedBeanDefinition(
            String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
            throws BeanDefinitionStoreException {
    
        synchronized (this.mergedBeanDefinitions) {
            RootBeanDefinition mbd = null;
    
            // 先从缓存拿合并的bd
            if (containingBd == null) {
                mbd = this.mergedBeanDefinitions.get(beanName);
            }
              //合并的bd为空就进行bd合并
            if (mbd == null) {
               //如果父类为空,就不进行bd合并
                if (bd.getParentName() == null) {
                    // Use copy of given root bean definition.
                    if (bd instanceof RootBeanDefinition) {
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    }
                    else {
                        mbd = new RootBeanDefinition(bd);
                    }
                }
                else {
                    // 进行bd合并
                    BeanDefinition pbd;
                    try {
                        String parentBeanName = transformedBeanName(bd.getParentName());
                        if (!beanName.equals(parentBeanName)) {
                           //父类的bd可能也需要合并,所以调用 getMergedBeanDefinition
                            pbd = getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            BeanFactory parent = getParentBeanFactory();
                            if (parent instanceof ConfigurableBeanFactory) {
                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                            }                       
                        }
                    }
                    //进行bd合并,子类覆盖父类的,如果子类没有,就用父类的属性
                    mbd = new RootBeanDefinition(pbd);
                    mbd.overrideFrom(bd);
                }
    
                // Set default singleton scope, if not configured before.
                if (!StringUtils.hasLength(mbd.getScope())) {
                    mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
                }
            }
    
            return mbd;
        }
    }
    
    复制代码
    
点赞
收藏
评论区
推荐文章
Irene181 Irene181
2年前
一篇文章带你搞懂Python中的继承和多态
一、继承的介绍继承是一种创建新的类的方式,新创建的叫子类,继承的叫父类、超类、基类。继承的特点就是子类可以使用父类的属性(特征、技能)。继承是类与类之间的关系。继承可以减少代码冗余、提高重用性。在现实生活中,继承一般指的是子女继承父辈的财产,如下图:二、如何用继承?1.继承语法Class派生类名(基类名):基类名写在括号里。在继承关系中,已有的,设计好
Bill78 Bill78
3年前
Python的新式类和旧式类
概述:Python中支持多继承,也就是一个子类可以继承多个父类/基类。当一个调用一个自身没有定义的属性时,它是按照何种顺序去父类中寻找的呢?尤其是当众多父类中都包含有同名的属性,这就涉及到新式类和经典类的区别。多继承:classFood(object):23def__init__(self,name,col
Easter79 Easter79
2年前
spring源码解析
前言上篇我们介绍了spring容器加载的方式,并重点介绍了基于xml配置解析和注解扫描两种容器加载的方式,封装和注册beandefinition的过程。今天我们分享BeanDefinition注册后的另一个重要过程bean的实例化过程的源码。容器加载流程!spring源码解析spring容器加载源码(bean实
Stella981 Stella981
2年前
Python Day24:类的继承、派生、覆盖、super()、绑定、非绑定方法
类的继承、派生、覆盖、super()python类的继承:子类继承父类,只需要在定义类的时候在类名后面加上(父类名)。继承之后,父类的属性方法、子类都可以访问派生:子类继承父类后,自己在父类的基础上,又添加了一些属于自己特性的属性、方法
Wesley13 Wesley13
2年前
Java的类继承
知识点1、继承作用:提高代码的重用性,继承之后子类可以继承父类中的属性和方法减少重复代码条件:子类和父类要满足isa的逻辑关系,才能使用继承。如:苹果isa水果语法:使用extends连接子类和父类。子类extends父类Java是单继承,一个类只能继承一个父类。子类不能继承父类私有的属性,但是可以
Wesley13 Wesley13
2年前
Java面试题(一)
看到一篇不错的java面试题的文章,自己整理一下,作为备用吧!Java面试题面向对象的特征有哪些方面?封装最常见的是把属性私有化封装在一个类里面,只能通过方法去访问继承子类继承父类,从而继承了父类的方法和属性抽象
Easter79 Easter79
2年前
Swift专题讲解十四——继承
Swift专题讲解十四——继承一、引言      Swift中,一个类可以从另一个类继承方法、属性、下标及其他特性。当一个类继承于另一个类时,这个类被称为子类,所继承的类被称为父类。在Swift中,继承是类区别于其他类型的主要特征。子类除了可以调用父类的属性,下标,方法外,其也可以对父类的属性,下标,方法进
Easter79 Easter79
2年前
Spring源码解析(三)BeanDefinition的载入、解析和注册
  通过上一篇源码的分析已经完成了BeanDefinition资源文件的定位,本篇继续分析BeanDefinition资源文件的载入和解析。AbstractBeanDefinitionReader的loadBeanDefinitions(Stringlocation,Set<ResouceactualResouces)方法完成定位,紧接着调用loa
Wesley13 Wesley13
2年前
Java基础知识笔记
Java基础知识笔记6继承6继承继承是一种由已创建的类创建新类的机制,利用继承,我们先创建一个共有属性的一般类,根据一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并根据需要增加他自己新的状态和行为,由继承得到的类称为子类,被继承的称为父类。Java中,一个子类只能继承一个父类,不支持多重继承;1继承的基
京东云开发者 京东云开发者
6个月前
带着问题去分析:Spring Bean 生命周期 | 京东物流技术团队
1:Bean在Spring容器中是如何存储和定义的Bean在Spring中的定义是org.springframework.beans.factory.config.BeanDefinition接口,BeanDefinition里面存储的就是我们编写的Jav