• (spring-第6回【IoC基础篇】)BeanDefinition——实例化Bean之前的第一大利器。


    上节讲了Bean实例化的内部机制,这里再复述一遍:

    1. ResourceLoader从系统中加载XML配置信息,并由Resource来表示。
    2. BeanDefinitionReader从Resource中读取配置信息,把配置文件中的<bean>解析成一个BeanDefinition对象,然后把BeanDefinition对象放到BeanDefinitionRegistry注册表中。
    3. 容器从BeanDefinitionRegistry注册表中扫描出Bean工厂后处理器的Bean(该Bean实现了BeanFactoryPostProcessor),用这个工厂后处理器来加工BeanDefinitionRegistry注册表中的所有BeanDefinition对象。具体做了两件事:
      1.   对使用到<bean>元素的占位符的Bean进行解析,把占位符转换成具体值,从而把半成品的BeanDefinition对象转为成品的对象。
      2.   扫描BeanDefinitionRegistry注册表中的所有BeanDefinition对象,通过java反射机制找出所有属性编辑器的Bean(实现了PropertyEditor的Bean),然后把它放到属性编辑器注册表中(PropertyEditorRegistry)。
    4. 容器从BeanDefinitionRegistry中取出加工过的BeanDefinition,并调用InstantiationStrategy着手bean的实例化工作。
    5. 在实例化Bean时,Spring容器使用BeanWrapper对Bean进行封装,BeanWrapper结合BeanDefinition以及属性编辑器完成Bean属性的设置工作。
    6. 利用容器中注册的Bean后处理器(该Bean实现了BeanPostProcessor)对第五步生成的Bean进行后续加工。

    从实例化的过程中可以看出,BeanDefinition起到中流砥柱的作用。因为BeanDefinition是配置文件<bean>元素标签在容器中的内部表示。比如,<bean>标签在XML中有class,scope,lazy-init等属性,那么在BeanDefinition中则有相应的beanClass,scope,lazyInit属性等。

    BeanDefinition接口的继承结构如图:

    顶级的BeanDefinition其实是个接口,下面的AbstractBeanDefinition实现了这个接口,而最下面的ChildBeanDefinition和RootBeanDefinition分别继承了AbstractBeanDefinition。来看一个XML配置:

     1  <!-- 父子<bean> -->
     2     <bean id="car0" class="com.baobaotao.tagdepend.Car" 
     3           p:brand="红旗CA72" p:price="2000.00" p:color="黑色"
     4           abstract="true"/>
     5           
     6     <bean id="car3" parent="abstractCar">
     7         <property name="color" value="红色"/>
     8     </bean>
            

    car3继承了car0,对应继承结构图,car3使用的是ChildBeanDefinition,car0使用的是RootBeanDefinition,也就是说,car3的属性多于car0,而不管是car3还是car0,它们都有共性(即使配置文件中没写,也是隐形存在的,比如上面讲的scope,lazyInit等),这些共性将提取在AbstractBeanDefinition中。如果<bean>标签没有继承关系,那么它将使用默认的RootBeanDefinition,在2.5版本之后加了一个GenericBeanDefinition,因为自身优势而成为默认的使用类。

    下面是BeanDefinition的API:(在线文档:http://tool.oschina.net/apidocs/apidoc?api=Spring-3.1.1)

     

     

    在方法概述中,我们可以看到这个接口中定义了所有<bean>属性的方法接口,比如singleton、prototype,lazyInit等。


    下面是AbstractBeanDefinition的结构图和API:

    由于API里的方法很多,我截取几个例子:

     

    这些get方法是获取共性类的属性值,实际上,共性属性的默认值在定义成员变量时就已经默认给定了,请看代码: 

     1 private volatile Object beanClass;
     2 
     3     private String scope = SCOPE_DEFAULT;
     4 
     5     private boolean singleton = true;
     6 
     7     private boolean prototype = false;
     8 
     9     private boolean abstractFlag = false;
    10 
    11     private boolean lazyInit = false;
    12 
    13     private int autowireMode = AUTOWIRE_NO;
    14 
    15     private int dependencyCheck = DEPENDENCY_CHECK_NONE;
    16 
    17     private String[] dependsOn;
    18 
    19     private boolean autowireCandidate = true;
    20 
    21     private boolean primary = false;

    上面代码截取的是AbstractBeanDefinition的源码,可以看到许多<bean>标签的属性默认值。

    一开始创建的BeanDefinition由于占位符的原因是个半成品,需要用Bean工厂后处理器对Bean进行处理,处理完之后由InstantiationStrategy对BeanDefinition进行实例化。后面我们会详细介绍InstantiationStrategy。

    BeanDefinition是如何创建的,XML又是如何被解析的?这些问题需要深入到源码中去寻求答案,在讲完IoC部分之后,我将对源码进行剖析,深入探究其奥妙,希望大家继续支持并关注我的博客。

  • 相关阅读:
    关于unittest框架的传参问题
    爬虫的框架:Scarpy
    Robot Frameworke在python3上搭建环境以及快捷方式的创建
    安装第三方模块报错:read time out
    操作正则表达式遇到的问题
    gil锁 线程队列 线程池
    并发编程
    网络编程传输文件
    粘包现象
    UDP协议下的socket
  • 原文地址:https://www.cnblogs.com/mesopotamia/p/4973285.html
Copyright © 2020-2023  润新知