重复是理解和记忆的最好方法。在讲实例化Bean的每个步骤之前,我都会先复习一下Bean实例化的整个过程:
结合图片我们回顾一下具体的过程:
今天我们将介绍的就是第五步。开门见山,BeanWrapper的功能:
spring通过BeanWrapper完成属性的配置工作。具体表现为:
下面是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利用属性描述器信息结合属性编辑器来设置属性。
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的属性进行编辑?下一篇博文将会详细介绍。