(spring-第11回【IoC基础篇】)BeanWrapper--实例化Bean的第四大利器
重复是理解和记忆的最好方法。在讲实例化Bean的每个步骤之前,我都会先复习一下Bean实例化的整个过程:

结合图片我们回顾一下具体的过程:
- ResourceLoader加载配置信息,
- 由BeanDefinitionReader读取并解析<bean>标签,并将<bean>标签的属性都转换为BeanDefinition对应的属性,并注册到BeanDefinitionRegistry注册表中。
- 容器扫描注册表,通过反射机制获取BeanFactoryPostProcessor类型的工厂后处理器,并用这个工厂后处理器对BeanDefinition进行加工。
- 取出加工过的BeanDefinition,使用InstantiationStrategy实例化Bean。
- BeanWrapper结合BeanDefinitionRegistry和PropertyEditorRegistry对Bean的属性赋值。
今天我们将介绍的就是第五步。开门见山,BeanWrapper的功能:
spring通过BeanWrapper完成属性的配置工作。具体表现为:
- 从BeanDefinitionRegistry注册表中取出尚未进行属性配置的BeanDefinition,获取Bean属性的配置信息,
- 使用属性编辑器对这些配置信息进行转换得到Bean属性的值,
- 最后对Bean通过反射机制设置属性值。
下面是BeanWrapper的继承结构:

从上面的结构可以看出,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利用属性描述器信息结合属性编辑器来设置属性。
public void setWrappedInstance(Object object, String nestedPath, Object rootObject) {
Assert.notNull(object, "Bean object must not be null");
this.object = object;
this.nestedPath = (nestedPath != null ? nestedPath : "");
this.rootObject = (!"".equals(this.nestedPath) ? rootObject : object);
this.nestedBeanWrappers = null;
this.typeConverterDelegate = new TypeConverterDelegate(this, object);
setIntrospectionClass(object.getClass());
}
protected void setIntrospectionClass(Class clazz) {
if (this.cachedIntrospectionResults != null &&
!clazz.equals(this.cachedIntrospectionResults.getBeanClass())) {
this.cachedIntrospectionResults = null;
}
}
2. 属性访问器:即PropertyAccessor,这个接口有很多方法,诸如:setPropertyValue、setPropertyValues等,BeanWrapperImpl通过这些方法来设置bean属性的值。
3. 属性编辑器注册表:(负责取出属性编辑器,BeanWrapperImpl结合属性编辑器来设置属性)。
下面是BeanWrapperImpl的某个构造函数,一开始就调用了从属性编辑器那里继承过来的registerDefaultEditors方法,该方法自动注册加载spring默认的属性编辑器们。
public BeanWrapperImpl(Object object) {
registerDefaultEditors();
setWrappedInstance(object);
}
BeanWrapperImpl完成Bean属性的配置工作之后,接下来还需要Bean后处理器(实现了BeanPostProcessor接口的Bean)继续对Bean实例进行加工,直到装配出一个准备就绪的Bean,把肉放到碗里等萌宝来吃。
由于本文未对代码进行详细解读,所以其中会有没有讲到的地方,比如,属性编辑器具体是怎样的?如何对bean的属性进行编辑?下一篇博文将会详细介绍。
(spring-第11回【IoC基础篇】)BeanWrapper--实例化Bean的第四大利器的更多相关文章
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(六)maven整合SSM
写在前面的话 承接前文<Spring+SpringMVC+MyBatis+easyUI整合基础篇(五)讲一下maven>,本篇所讲述的是如何使用maven与原ssm项目整合,使得一个普 ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(八)mysql中文查询bug修复
写在前面的话 在测试搜索时出现的问题,mysql通过中文查询条件搜索不出数据,但是英文和数字可以搜索到记录,中文无返回记录.本文就是写一下发现问题的过程及解决方法.此bug在第一个项目中点这里还存在, ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(十一)SVN服务器进阶
日常啰嗦 上一篇文章<Spring+SpringMVC+MyBatis+easyUI整合基础篇(十)SVN搭建>简单的讲了一下SVN服务器的搭建,并没有详细的介绍配置文件及一些复杂的功能, ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(十二)阶段总结
不知不觉,已经到了基础篇的收尾阶段了,看着前面的十几篇文章,真的有点不敢相信,自己竟然真的坚持了下来,虽然过程中也有过懒散和焦虑,不过结果还是自己所希望的,克服了很多的问题,将自己的作品展现出来,也发 ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇
基础篇 Spring+SpringMVC+MyBatis+easyUI整合基础篇(一)项目简介 Spring+SpringMVC+MyBatis+easyUI整合基础篇(二)牛刀小试 Spring+S ...
- (spring-第2回【IoC基础篇】)Spring的Schema,基于XML的配置
要深入了解Spring机制,首先需要知道Spring是怎样在IoC容器中装配Bean的.而了解这一点的前提是,要搞清楚Spring基于Schema的Xml配置方案. 在深入了解之前,必须要先明白几个标 ...
- (spring-第5回【IoC基础篇】)spring容器从加载配置文件到实例化bean的内部工作机制
前面讲过,spring的生命周期为:实例化前奏-->实例化-->实例化后期-->初始化前期-->初始化-->初始化后期-->bean的具体调用-->销毁前-- ...
- (spring-第3回【IoC基础篇】)spring的依赖注入-属性、构造函数、工厂方法等的注入(基于XML)
Spring要把xml配置中bean的属性实例化为具体的bean,"依赖注入"是关卡.所谓的"依赖注入",就是把应用程序对bean的属性依赖都注入到spring ...
- (spring-第1回【IoC基础篇】)Spring容器中Bean的生命周期
日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...
- (spring-第13回【IoC基础篇】)PropertyEditor(属性编辑器)--实例化Bean的第五大利器
上一篇讲到JavaBeans的属性编辑器,编写自己的属性编辑器,需要继承PropertyEditorSupport,编写自己的BeanInfo,需要继承SimpleBeanInfo,然后在BeanIn ...
随机推荐
- Ubuntu 14.04 分区方案
我磁盘大概还有70多G的空间吧,我全部拿来使用的.真实的双系统哦. 一般来讲,linux系统分区最少要包括/和/swap两个.这样据说会影响性能,没有这样安装过,就无从考证啦.其实就是重装系统的时候, ...
- [backbone] Getting Started with Backbone.js
一.简介 Backbone 是一个 JavaScript MVC 框架,它属于轻量级框架,且易于学习掌握.模型.视图.集合和路由器从不同的层面划分了应用程序,并负责处理几种特定事件.处理 Ajax 应 ...
- Qt之Concurrent框架
简述 QtConcurrent命名空间提供了一个高级API来编写多线程程序,而无需使用低级线程原语,例如:互斥.读写锁.等待条件或信号量.使用QtConcurrent编写的程序使用的线程数量会自动根据 ...
- WMI执行远程文件(RPC)
通过wmi在远程机上执行命令(wmi:windows management interface 可以通过一个公共的接口访问不同操作系统(windows系统)的构成单元,利用它可以高效的管理远程和本地的 ...
- SQL Server 自定义函数(1)把某一列多行的值拼接成一个字符串
) SET @resultstr='' SELECT @resultstr=@resultstr+'|'+[BaseImage] FROM dbo.life_fc PRINT @resultstr 示 ...
- 根据采购/销售订单创建STO/SO
FUNCTION Z_SD_CREATE_DN. *"-------------------------------------------------------------------- ...
- linux下git的安装和使用(转)
转自:http://www.cnblogs.com/sunada2005/archive/2013/06/06/3121098.html 最近在使用github,感觉不错.在windows下,可使用g ...
- css改变图片的颜色
参考大神张鑫旭:http://www.zhangxinxu.com/wordpress/2016/06/png-icon-change-color-by-css/ 主要知识点:border-right ...
- pandas进行数据分析需要的一些操作
一.查看数据 1.查看DataFrame前xx行或后xx行a=DataFrame(data);a.head(6)表示显示前6行数据,若head()中不带参数则会显示全部数据.a.tail(6)表示显示 ...
- 存储过程Oracle学习(一)
一.简介 存储过程:就是在数据库中创建的一段程序,供别人调用 .其实我感觉跟定义一个方法相似 二.无参存储过程 如下,经典的输出"Hello World"来入门存储过程 创建一个存 ...