浏览 5503 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-01-04
在IoC容器实例化Bean后,Bean只是个半成品,IoC容器将调用BeanWrapper的实现类BeanWrapperImp对这个实例进行属性值填充的后续工作。BeanWrapperImpl的类结构如下所示: PropertyEditorRegistry | PropertyEditorRegistrySupport | BeanWrapper AbstractPropertyAccessor | | |___________________| | BeanWrapperImpl 在PropertyEditorRegistrySupport中定义了两个Map类型的defaultEditors和customEditors,用于存放常见类型(String Integer等原子类型)和自定义类型的属性编辑器。 private Map defaultEditors; private Map customEditors; 所以,BeanWrapperImpl也拥有继承了这些编辑器,但是我有一点不明白的是,为什么BeanWrapperImpl不是容器级的,而是Bean级的:即在容器主控制程序中,每实例化一个Bean时,都要new一个BeanWrapperImpl实例出来,请看: protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mergedBeanDefinition) throws BeansException { Object beanInstance = getInstantiationStrategy().instantiate(mergedBeanDefinition, beanName, this); [b]BeanWrapper bw = new BeanWrapperImpl(beanInstance);[/b] initBeanWrapper(bw); return bw; } 这样一来属性编辑器的实例会被多次创建,因为每个BeanWrapperImpl对应一套属性编辑器,而在我看来这些属性编辑器应该是容器级的,也就是说只要保存一份就可以了,现在的情况是每创建一个Bean都对应一份,不但没有必要,而且浪费资源。 不知道是我没有看出其中的机巧,还是Rod的设计失误,请大家帮助分析一下,不胜感激。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-01-04
我没有看过源代码,乱说两句,之所以叫Wrapper,实际是一个包装,但是Bean是有状态的,所以Wapper是有状态的!如果无状态那叫BeanTools了
|
|
返回顶楼 | |
发表时间:2007-01-04
jamesby 写道 我没有看过源代码,乱说两句,之所以叫Wrapper,实际是一个包装,但是Bean是有状态的,所以Wapper是有状态的!如果无状态那叫BeanTools了
Bean是有状态,但是属性编辑器是可以共用的,象目前的代码,每一个BeanWrapperImpl都对应一套独立的属性编辑器(如Integer.class 对应IntegerEditor,Boolean.class对应BooleanEditor),我觉得这些属性编辑器是容器级的,不应该放到BeanWrapperImpl,BeanWrapperImpl只需要引用到这些属性编辑器就可以了。这正是我疑问的地方。 |
|
返回顶楼 | |
发表时间:2007-01-05
恩,不过如果说是Rod的设计失误,我不赞同,说这句话之前先确认自己是否真正读懂了代码,我过两天也瞧瞧Spring启动过程的代码,共同学习。
|
|
返回顶楼 | |
发表时间:2007-01-05
我今天再仔细看了一下,我想大概是这样的:
属性编辑器因为需要保存转换过程中的状态,所以也不是线程安全的,所以Spring为每个Bean都提供一套属性编辑器。如果要使容器中所有Bean共享属性编辑器,就必须让编辑器内编辑对象的状态做到线程安全,如采用ThreadLocal,不过这样一来,编辑器的设计就比较复杂了。 另外,我们可以知道IDE中的属性编辑器,是共享的,而非每个组件对应一套自己的编辑器实例,这是因为在开发时,属性编辑器没有线程安全问题,IDE一般就同时提供一个编辑窗口。而Spring容器的环境下,情况就复杂了,可能会有两个线程同时创建Bean,所以它对应的编辑器就得分家了。 |
|
返回顶楼 | |
发表时间:2007-01-05
stamen说的不错,关键是PropertyEditor不是线程安全的。因此defaultEditors没办法公用,只能每次创建。
不过从性能看,现代JVM创建小对象的代价非常非常小,在实际应用中,这点性能消耗不会成为瓶颈。 而且我以前也专门针对这个问题测试过,只是第一次load class会有较大的性能损耗(需要load很多PropertyEditor),后续创建一个BeanWrapperImpl的成本可以忽略不计。 |
|
返回顶楼 | |
发表时间:2007-01-05
joachimz 写道 stamen说的不错,关键是PropertyEditor不是线程安全的。因此defaultEditors没办法公用,只能每次创建。 因为PropertyEditor不是线程安全的,但是从Spring的代码可以看出PropertyEditor是在BeanWrapper中声明的。
不过从性能看,现代JVM创建小对象的代价非常非常小,在实际应用中,这点性能消耗不会成为瓶颈。 而且我以前也专门针对这个问题测试过,只是第一次load class会有较大的性能损耗(需要load很多PropertyEditor),后续创建一个BeanWrapperImpl的成本可以忽略不计。 这样对于prototype类型的Bean没有问题,一个Bean一个BeanWrapper 但是对于singleton的Bean则有问题了,存在多个线程共用一个Bean的情况,也就是多个线程共用一个BeanWrapper的情况? 除非Spring对singleton类型的Bean创建多个BeanWrapper? 或者Spring只在某个时刻用到BeanWrapper,如加载的时候? 当然代码没有读,准备读。 |
|
返回顶楼 | |
发表时间:2007-01-06
我理解错了,今天粗读了一下相关代码,应该是这样的:
BeanWrapper的生命周期很短,在得到Bean实例的时候BeanWrapper就结束了. 而且PropertyEditor,CustomerEditor只有在getBean的时候才会用到,因此也不存在什么多个时刻用到BeanWrapper. |
|
返回顶楼 | |
发表时间:2007-01-06
对于singleton确实是这样,但对应prototype,request,session和globalSession则会多次调用,性能问题还是会有的,我觉得至少可以智能你装入属性编辑器,而不是每个BeanWrapper都有一套完整的属性编辑器,假设某个Service的Bean,它仅注入一些Dao,但这个Bean的BeanWrapper也会拥有32个默认的属性编辑器实例。
|
|
返回顶楼 | |
发表时间:2007-01-07
stamen 写道 对于singleton确实是这样,但对应prototype,request,session和globalSession则会多次调用,性能问题还是会有的,我觉得至少可以智能你装入属性编辑器,而不是每个BeanWrapper都有一套完整的属性编辑器,假设某个Service的Bean,它仅注入一些Dao,但这个Bean的BeanWrapper也会拥有32个默认的属性编辑器实例。 恩,确实是这样,那是否Spring的初衷是为所有的Bean的配置尽量为Singleton呢?胡乱猜测大师想法.
|
|
返回顶楼 | |