前言

BeanDefinitionSpring中的非常重要的一个类,学习SpringbootSpring时,会常常遇到该类,所以本篇文章会对BeanDefinition的概念进行入门学习,同时一并学习定义注册,移除和查问BeanDefinitionBeanDefinitionRegistry接口。本篇文章用于帮忙了解BeanDefinition的概念,同时作为笔者学习Springboot的笔记,有概念谬误的中央敬请批评指正。

Springboot版本:2.4.1

注释

一. BeanDefinition简析

BeanDefinitionSpring中的重要接口,BeanDefinition的实现类用于形容Spring中的一个应该被实例化的bean的各种性质,包含bean的属性值,构造函数,办法等信息,除此之外,还额定形容beanSpring容器中的作用域,bean名称等信息。

能够将BeanDefinition类比于Java中的类的Class对象,在Java中能够应用一个类的Class对象来实现对象的实例化,然而在Spring中,单纯应用beanClass对象无奈实现bean的实例化,因为Spring中的bean具备一些额定的性质,例如bean是否是单例,bean是否在容器中是懒加载,bean在容器中的名字,这些性质无奈依附类的Class对象来形容,所以Spring引入BeanDefinition来形容Spring中的一个应该被实例化的bean的各种性质。

Spring框架在启动时,会在ConfigurationClassPostProcessor这个bean工厂后置处理器中将须要被加载到容器中的bean扫描到并创立BeanDefinition,而后缓存到BeanFactorybeanDefinitionMap中,beanDefinitionMap是一个Map,用于寄存BeanDefinition,键为bean在容器中的名称,值为bean对应的BeanDefinition

当初以Springboot启动为例,简要展现ConfigurationClassPostProcessor将须要被加载到容器中的bean扫描到并创立BeanDefinition而后放到beanDefinitionMap中的一个流程。在Springboot启动时,会先创立容器(也叫利用上下文),而后调用SpringApplicationrefreshContext()办法来初始化容器,在refreshContext()办法中会最终调用到容器的refresh()办法来实现初始化,这个调用链能够示意如下。

AbstractApplicationContextrefresh()办法中,会调用invokeBeanFactoryPostProcessors()办法来调用bean工厂后置处理器,ConfigurationClassPostProcessor就会在这里被调用,具体的ConfigurationClassPostProcessor的逻辑这里临时不剖析,当初将断点打到AbstractApplicationContext#refresh()办法中调用invokeBeanFactoryPostProcessors()办法的这一行代码,此时察看BeanFactory中的beanDefinitionMap如下所示。

当时曾经定义好了一个bean,如下所示。

@Componentpublic class TestBean {    public TestBean() {        System.out.println("Initialize TestBean.");    }}

此时往后执行一步,再察看BeanFactory中的beanDefinitionMap如下所示。

能够看到BeanFactory中的beanDefinitionMap多了很多BeanDefinition,其中也包含当时定义好的TestBean,这是因为在ConfigurationClassPostProcessor中会将须要被加载到容器中的bean都扫描进去并创立成BeanDefinition,而后寄存到beanDefinitionMap中,然而TestBean的构造函数中应该被打印的信息是没有被打印的,这阐明ConfigurationClassPostProcessor中只会创立BeanDefinition并存放到beanDefinitionMap中,不会理论的实例化bean,真正的bean的实例化由AbstractApplicationContextfinishBeanFactoryInitialization()办法开启,这里暂不剖析。

当初可知,Spring借助BeanDefinition来创立容器中的bean,容器中的每一个bean都会由一个BeanDefinition来形容,形容包含bean属性值,构造函数,办法,bean作用域,bean名称等信息,Spring在启动时会先扫描所有须要被加载到容器中的bean,而后为这些bean创立BeanDefinition并增加到BeanFactory中的beanDefinitionMap中。创立BeanDefinition时不会实例化beanbean的实例化在BeanDefinition创立之后。

二. BeanDefinitionRegistry简析

Springboot启动时,会创立容器,并依据WebApplicationType的不同,创立不同的容器,例如WebApplicationTypeSERVLET,此时应用的容器为AnnotationConfigServletWebServerApplicationContext,如果WebApplicationTypeNONE,此时应用的容器为AnnotationConfigApplicationContext,无论应用哪种容器,其外部持有一个BeanFactory容器,其理论类型为DefaultListableBeanFactoryDefaultListableBeanFactory是一个具备注册性能的容器,因为其实现了BeanDefinitionRegistry接口。

BeanDefinitionRegistry接口定义了对BeanDefinition的注册,移除和查问等操作,上面次要看一下DefaultListableBeanFactoryBeanDefinition的注册的实现,即registerBeanDefinition()办法,源码如下。

@Overridepublic 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);        }    }    //通过beanName将曾经注册的BeanDefinition获取进去    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);    if (existingDefinition != null) {        //如果曾经应用以后beanName注册过BeanDefinition        //则判断是否容许以雷同beanName注册不同的BeanDefinition以笼罩已存在的BeanDefinition        if (!isAllowBeanDefinitionOverriding()) {            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);        }        else if (existingDefinition.getRole() < beanDefinition.getRole()) {            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 {        //查看bean实例是否曾经开始创立        if (hasBeanCreationStarted()) {            synchronized (this.beanDefinitionMap) {                //将BeanDefinition缓存到beanDefinitionMap                this.beanDefinitionMap.put(beanName, beanDefinition);                //将beanName缓存到beanDefinitionNames                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);                updatedDefinitions.addAll(this.beanDefinitionNames);                updatedDefinitions.add(beanName);                this.beanDefinitionNames = updatedDefinitions;                //从manualSingletonNames中将beanName移除,以避免beanName反复                //manualSingletonNames中缓存了手动注册的单例的名称                removeManualSingletonName(beanName);            }        }        else {//仍处于启动注册阶段            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();    }}

DefaultListableBeanFactory实现的registerBeanDefinition()办法中,会将beanNameBeanDefinition以键值对的模式缓存到beanDefinitionMap中,同时还会将beanName增加到beanDefinitionNames中。因为还会存在手动注册单例bean的状况,如果手动注册了单例bean,单例bean的名称会缓存在manualSingletonNames中,所以还须要在registerBeanDefinition()办法中保障beanDefinitionNamesmanualSingletonNames中的beanName不反复。

当初做一个大节,在Springboot启动时,创立的容器中会持有一个DefaultListableBeanFactory容器,其实现了BeanDefinitionRegistry接口,具备对BeanDefinition进行注册,删除和查问等性能,Springboot进行bean的扫描加载,主动拆卸时均会基于须要加载到容器中的bean创立BeanDefinition,并将创立好的BeanDefinition注册到DefaultListableBeanFactory容器中。

总结

BeanDefinition的次要作用是形容Spring中的bean,作用能够类比于Java中的Class对象,然而比Class对象可能形容更多的bean信息,例如bean作用域,是否懒加载等。在Springboot的启动阶段,每个须要被加载到容器中的bean会被创立为一个BeanDefinition,而后被注册到容器中,而Springboot中应用的容器均持有一个DefaultListableBeanFactory,其实现了BeanDefinitionRegistry接口,所以注册BeanDefinition到容器中,理论就是注册BeanDefinitionDefaultListableBeanFactory中,最终每个BeanDefinition会被缓存到DefaultListableBeanFactorybeanDefinitionMap中。

BeanDefinition只是一个接口,其有许多实现类,在本篇文章中并为进行剖析,同时在BeanDefinition的创立过程中还有一个重要类ConfigurationClassPostProcessor,本篇文章也并未深刻探索,上述的问题,将在后续的文章中逐个阐明。