Spring IOC - BeanDefinition解析

1. BeanDefinition的属性        

        BeanDefinition作为接口定义了属性的get、set方法。这些属性基本定义在其直接实现类AbstractBeanDefinition中,各属性的含义如下表所示:

类型

名称

含义

常量

SCOPE_DEFAULT

默认作用域:单例模式

AUTOWIRE_NO

没有自动装配

AUTOWIRE_BY_NAME

按名称自动装配

AUTOWIRE_BY_TYPE

按类型自动装配

AUTOWIRE_CONSTRUCTOR

按最匹配的构造方法自动装配

AUTOWIRE_AUTODETECT

对bean类进行内省来确定合适的自动装配策略

DEPENDENCY_CHECK_NONE

不进行依赖关系依赖关系检查

DEPENDENCY_CHECK_OBJECTS

对对象引用进行依赖关系检查

DEPENDENCY_CHECK_SIMPLE

对简单属性进行依赖关系检查

DEPENDENCY_CHECK_ALL

对所有属性进行依赖关系检查

INFER_METHOD

容器应尝试推断销毁方法名称,而不是显示指定方法名称

属性变量

beanClass

Bean 的Class对象

scope

作用域,默认为单例

abstractFlag

是否是抽象类标记,默认值为false,若为true,则不会实例化该bean

lazyInit

是否懒加载

autowireMode

自动装配模式,默认无

dependencyCheck

依赖关系检查,默认无

dependsOn

Bean依赖的其他Bean的名称

autowireCandidate

这个bean是否是自动装配到其他bean的候选项,默认为true

priary

这个bean是否是首要的自动装配候选项,默认为false

qulifiers

自动装配候选项限定符map,key:class对象名称(全类名)

instanceSupplier

为创建bean实例指定一个回调函数,作为声明性工厂方法的替代方案

nonPublicAccessAllowed

是否允许访问非公共的构造函数和方法,默认为true,标识允许

lenientConstructorResolution

是否以宽松模式或严格模式解析构造函数,默认为true,为宽松模式

factoryBeanName

工厂bean名称

factoryMethodName

工厂方法名称

constructorArgumentValues

构造函数参数值

propertyValues

属性值

methodOverrides

当前bean被重写的方法

initMethodName

初始化的方法的名称

destroyMethodName

销毁的方法的名称

enforceInitMethod

指定配置的方法是否为初始化方法,默认为true

enforceDestroyMethod

指定配置的方法是否为销毁方法,默认为true

synthetic

beanDefiniton是否是合成的,默认为false

role

角色提示,指BeanDefinition是应用程序的主要部分。通常是由用户定义的bean

description

beanDefiniton可读性高的描述

resource

beanDefinition来自的资源

2. 三个子类及属性        

        AbstractBeanDefinition有三个重要的直接子类,他们除了拥有父类的这些属性外,自己也有专门的属性,首先其类图如下所示:

Spring IOC - BeanDefinition解析_第1张图片

        三个直接子类各自的属性如下表所示:

子类

属性名称

属性含义

GenericBeanDefinition

parentName

父bean名称

ChildBeanDefinition

parentName

父bean名称

RootBeanDefinition

decoratedDefinition

记录了beanName,别名等

qualifiedElement

记录了注解元素

stale

beanDefinition是否需要被重新合并

allowCaching

是否允许缓存,默认为true

isFactoryMethodUnique

工厂方法是否唯一,默认为false

resolvedTargetType

缓存class,表明RootBeanDefinition存储哪个类的信息

isFactoryBean

表名该Bean是否是工厂bean

factoryMethodReturnType

缓存工厂方法的返回类型

resolvedDestroyMethodName

缓存已解析的销毁方法名称

resolvedConstructorOrFactoryMethod

缓存已解析的构造函数或工厂方法

constructorArgumentsResolved

表明构造函数参数是否解析完毕,默认为false

resolvedConstructorArguments

缓存完成解析的构造函数参数

preparedConstructorArguments

缓存待解析的构造函数参数

postProcessed

表名是否被MergedBeanDefinitionPostProcessor处理过,默认为false

beforeInstantiationResolved

在生成代理时使用,表名是否已经生成代理

externallyManagedConfigMembers

记录了Contructor、Field、method类型的成员

externallyManagedInitMethods

InitializingBean中的init回调函数名,以便进行生命周期回调

externallyManagedDestroyMethods

DisposableBean的destroy回调函数名,以便进行生命周期回调

3. 三个子类的应用及区别

        在XML文件中定义一个bean时,Spring会创建一个RootBeanDefinition实例,这个实例会保存所有的配置信息,如类名、属性值等;

        当一个bean继承了另一个bean时,Spring会为子bean创建一个ChildBeanDefinition,为父bean创建一个RootBeanDefinition

        在配置类中使用@Bean注解定义bean时,Spring会创建一个GenericBeanDefinition实例;

        在类上使用注解(如@Component、@Service、@Repository等)来定义一个bean时,Spring会创建一个实现了AnnotatedBeanDefinition接口的实例:AnnotatedGenericBeanDefinitionScannedGenericBeanDefinition。这个实例会保存类名、类的类型、以及类上的所有注解信息;

    GenericBeanDefinitionAnnotatedBeanDefinition的主要区别如下:

        AnnotatedBeanDefinition保存了类上的注解信息,而GenericBeanDefinition没有。这就使得Spring能够在运行时读取和处理这些注解,提供更丰富的功能。

4. BeanDefinition的合并

        Spring中提供了多样的BeanDefinition,其最后都会被转换或合并为RootBeanDefinition,就是把子 BeanDefinition 的配置信息和父 BeanDefinition 的配置信息合并起来,形成一个完整的配置信息。合并后的 BeanDefinition 对象包含了 Bean 创建所需要的所有信息,Spring 将使用这个完整的 BeanDefinition 来创建 Bean 实例。

5. BeanDefinition的合并解析

        代码位于:AbstractBeanFactory#getMergedBeanDefinition

protected RootBeanDefinition getMergedBeanDefinition(
      String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
      throws BeanDefinitionStoreException {

   synchronized (this.mergedBeanDefinitions) {
      RootBeanDefinition mbd = null;
      RootBeanDefinition previous = null;

      // Check with full lock now in order to enforce the same merged instance.
      if (containingBd == null) {
         mbd = this.mergedBeanDefinitions.get(beanName);
      }

      if (mbd == null || mbd.stale) {
         previous = mbd;
         // 父bean为空
         if (bd.getParentName() == null) {
            // Use copy of given root bean definition.
            if (bd instanceof RootBeanDefinition) {
               // 原始的BeanDefinition为RootBeanDefinition,直接克隆
               mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
            }
            else {
               // 原始的BeanDefinition不是RootBeanDefinition,则new一个
               mbd = new RootBeanDefinition(bd);
            }
         }
         else {
            // 父bean不为空,需要合并
            // Child bean definition: needs to be merged with parent.
            BeanDefinition pbd;
            try {
               String parentBeanName = transformedBeanName(bd.getParentName());
               if (!beanName.equals(parentBeanName)) {
                  // 获取map中parentBeanName对应的RootBeanDefinition
                  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);
            }
            // Deep copy with overridden values.
            // 深拷贝
            mbd = new RootBeanDefinition(pbd);
            // 子bean初始化BeanDefinition的相关信息覆盖掉继承自RootBeanDefinition的相同信息
            mbd.overrideFrom(bd);
         }

         // Set default singleton scope, if not configured before.
         if (!StringUtils.hasLength(mbd.getScope())) {
            mbd.setScope(SCOPE_SINGLETON);
         }

         // A bean contained in a non-singleton bean cannot be a singleton itself.
         // Let's correct this on the fly here, since this might be the result of
         // parent-child merging for the outer bean, in which case the original inner bean
         // definition will not have inherited the merged outer bean's singleton status.
         if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
            mbd.setScope(containingBd.getScope());
         }

         // Cache the merged bean definition for the time being
         // (it might still get re-merged later on in order to pick up metadata changes)
         if (containingBd == null && isCacheBeanMetadata()) {
            this.mergedBeanDefinitions.put(beanName, mbd);
         }
      }
      if (previous != null) {
         copyRelevantMergedBeanDefinitionCaches(previous, mbd);
      }
      return mbd;
   }
}

        逻辑流程图如下所示:

Spring IOC - BeanDefinition解析_第2张图片

        总结如下:

        若bean没有父亲,将当前beanDefinition通过克隆或深拷贝方式生成一个新的RootBeanDefinition,并返回;

        若bean有父亲,将父beanDefinition通过克隆或深拷贝方式生成一个新的RootBeanDefinition,再将子beanDefiniton属性覆盖RootBeanDefiniton的相同信息,并返回该RootBeanDefinition.

你可能感兴趣的:(Spring,spring,java,后端)