转载

(spring-第11回【IoC基础篇】)BeanWrapper--实例化Bean的第四大利器

重复是理解和记忆的最好方法。在讲实例化Bean的每个步骤之前,我都会先复习一下Bean实例化的整个过程:

(spring-第11回【IoC基础篇】)BeanWrapper--实例化Bean的第四大利器

结合图片我们回顾一下具体的过程:

  1. ResourceLoader加载配置信息,
  2. 由BeanDefinitionReader读取并解析<bean>标签,并将<bean>标签的属性都转换为BeanDefinition对应的属性,并注册到BeanDefinitionRegistry注册表中。
  3. 容器扫描注册表,通过反射机制获取BeanFactoryPostProcessor类型的工厂后处理器,并用这个工厂后处理器对BeanDefinition进行加工。
  4. 取出加工过的BeanDefinition,使用InstantiationStrategy实例化Bean。
  5. BeanWrapper结合BeanDefinitionRegistry和PropertyEditorRegistry对Bean的属性赋值。

今天我们将介绍的就是第五步。开门见山,BeanWrapper的功能:

spring通过BeanWrapper完成属性的配置工作。具体表现为:

  1. 从BeanDefinitionRegistry注册表中取出尚未进行属性配置的BeanDefinition,获取Bean属性的配置信息,
  2. 使用属性编辑器对这些配置信息进行转换得到Bean属性的值,
  3. 最后对Bean通过反射机制设置属性值。

下面是BeanWrapper的继承结构:

(spring-第11回【IoC基础篇】)BeanWrapper--实例化Bean的第四大利器

从上面的结构可以看出,BeanWrapperImpl(BeanWrapper的实现类)有两个顶级接口,分别是:PropertyEditorRegistry和PropertyAccessor,前者是属性编辑器,负责将配置文件中bean属性的字面值转换为bean具体的属性值。后者定义了各种访问bean属性的方法。所以BeanWrapperImpl具有三重身份:

1. Bean包裹器:(顾名思义)

下面代码是BeanWrapperImpl初始化时要执行的方法,而参数中的object就是包裹的bean对象。

其中第8行就是把object.getClass()保存在cachedIntrospectionResults 属性中,该属性是CachedIntrospectionResults类的实例,

CachedIntrospectionResults 是负责缓存 属性描述器 (PropertyDescriptor)信息的。

object是对象的实例,而object.getClass()则获取的是实例对应的类的描述信息,那么cachedIntrospectionResults 拿到这个实例类的描述信息class,就可以通过反射机制来访问该class里面的所有属性了,最后封装成PropertyDescriptor。

属性描述器(PropertyDescriptor)是 java.beans.PropertyDescriptor包里的类,用来描述java bean的属性(一个描述器描述一个属性),这个属性是JavaBean通过一对入口方法导出的。

BeanWrapperImpl利用属性描述器信息结合属性编辑器来设置属性。

1 public void setWrappedInstance(Object object, String nestedPath, Object rootObject) { 2         Assert.notNull(object, "Bean object must not be null"); 3         this.object = object; 4         this.nestedPath = (nestedPath != null ? nestedPath : ""); 5         this.rootObject = (!"".equals(this.nestedPath) ? rootObject : object); 6         this.nestedBeanWrappers = null; 7         this.typeConverterDelegate = new TypeConverterDelegate(this, object); 8         setIntrospectionClass(object.getClass()); 9     }  1 protected void setIntrospectionClass(Class clazz) { 2         if (this.cachedIntrospectionResults != null && 3                 !clazz.equals(this.cachedIntrospectionResults.getBeanClass())) { 4             this.cachedIntrospectionResults = null; 5         } 6     }   

2. 属性访问器:即PropertyAccessor,这个接口有很多方法,诸如:setPropertyValue、setPropertyValues等,BeanWrapperImpl通过这些方法来设置bean属性的值。

3. 属性编辑器注册表:(负责取出属性编辑器,BeanWrapperImpl结合属性编辑器来设置属性)。

下面是BeanWrapperImpl的某个构造函数,一开始就调用了从属性编辑器那里继承过来的registerDefaultEditors方法,该方法自动注册加载spring默认的属性编辑器们。

1 public BeanWrapperImpl(Object object) { 2         registerDefaultEditors(); 3         setWrappedInstance(object); 4     }

BeanWrapperImpl完成Bean属性的配置工作之后,接下来还需要Bean后处理器(实现了BeanPostProcessor接口的Bean)继续对Bean实例进行加工,直到装配出一个准备就绪的Bean,把肉放到碗里等萌宝来吃。

由于本文未对代码进行详细解读,所以其中会有没有讲到的地方,比如,属性编辑器具体是怎样的?如何对bean的属性进行编辑?下一篇博文将会详细介绍。

正文到此结束
Loading...