困惑:哪位高手能帮小弟我解答一个关于BeanWrapperImpl设计的有关问题

困惑:谁能帮我解答一个关于BeanWrapperImpl设计的问题
   最近在分析Spring的源码,但对其中一个问题很困惑,现描述如下,希望各位帮忙分析一下:
   在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的设计失误,请大家帮助分析一下,不胜感激。
1 楼 jamesby 2007-01-04  
我没有看过源代码,乱说两句,之所以叫Wrapper,实际是一个包装,但是Bean是有状态的,所以Wapper是有状态的!如果无状态那叫BeanTools了
2 楼 stamen 2007-01-04  
jamesby 写道
我没有看过源代码,乱说两句,之所以叫Wrapper,实际是一个包装,但是Bean是有状态的,所以Wapper是有状态的!如果无状态那叫BeanTools了

   Bean是有状态,但是属性编辑器是可以共用的,象目前的代码,每一个BeanWrapperImpl都对应一套独立的属性编辑器(如Integer.class 对应IntegerEditor,Boolean.class对应BooleanEditor),我觉得这些属性编辑器是容器级的,不应该放到BeanWrapperImpl,BeanWrapperImpl只需要引用到这些属性编辑器就可以了。这正是我疑问的地方。
3 楼 jamesby 2007-01-05  
恩,不过如果说是Rod的设计失误,我不赞同,说这句话之前先确认自己是否真正读懂了代码,我过两天也瞧瞧Spring启动过程的代码,共同学习。
4 楼 stamen 2007-01-05  
我今天再仔细看了一下,我想大概是这样的:
  
   属性编辑器因为需要保存转换过程中的状态,所以也不是线程安全的,所以Spring为每个Bean都提供一套属性编辑器。如果要使容器中所有Bean共享属性编辑器,就必须让编辑器内编辑对象的状态做到线程安全,如采用ThreadLocal,不过这样一来,编辑器的设计就比较复杂了。
   另外,我们可以知道IDE中的属性编辑器,是共享的,而非每个组件对应一套自己的编辑器实例,这是因为在开发时,属性编辑器没有线程安全问题,IDE一般就同时提供一个编辑窗口。而Spring容器的环境下,情况就复杂了,可能会有两个线程同时创建Bean,所以它对应的编辑器就得分家了。
5 楼 joachimz 2007-01-05  
stamen说的不错,关键是PropertyEditor不是线程安全的。因此defaultEditors没办法公用,只能每次创建。
不过从性能看,现代JVM创建小对象的代价非常非常小,在实际应用中,这点性能消耗不会成为瓶颈。
而且我以前也专门针对这个问题测试过,只是第一次load class会有较大的性能损耗(需要load很多PropertyEditor),后续创建一个BeanWrapperImpl的成本可以忽略不计。
6 楼 jamesby 2007-01-05  
joachimz 写道
stamen说的不错,关键是PropertyEditor不是线程安全的。因此defaultEditors没办法公用,只能每次创建。
不过从性能看,现代JVM创建小对象的代价非常非常小,在实际应用中,这点性能消耗不会成为瓶颈。
而且我以前也专门针对这个问题测试过,只是第一次load class会有较大的性能损耗(需要load很多PropertyEditor),后续创建一个BeanWrapperImpl的成本可以忽略不计。
因为PropertyEditor不是线程安全的,但是从Spring的代码可以看出PropertyEditor是在BeanWrapper中声明的。

这样对于prototype类型的Bean没有问题,一个Bean一个BeanWrapper
但是对于singleton的Bean则有问题了,存在多个线程共用一个Bean的情况,也就是多个线程共用一个BeanWrapper的情况?

除非Spring对singleton类型的Bean创建多个BeanWrapper?

或者Spring只在某个时刻用到BeanWrapper,如加载的时候?

当然代码没有读,准备读。
7 楼 jamesby 2007-01-06  
我理解错了,今天粗读了一下相关代码,应该是这样的:
BeanWrapper的生命周期很短,在得到Bean实例的时候BeanWrapper就结束了.

而且PropertyEditor,CustomerEditor只有在getBean的时候才会用到,因此也不存在什么多个时刻用到BeanWrapper.
8 楼 stamen 2007-01-06  
对于singleton确实是这样,但对应prototype,request,session和globalSession则会多次调用,性能问题还是会有的,我觉得至少可以智能你装入属性编辑器,而不是每个BeanWrapper都有一套完整的属性编辑器,假设某个Service的Bean,它仅注入一些Dao,但这个Bean的BeanWrapper也会拥有32个默认的属性编辑器实例。
9 楼 jamesby 2007-01-07  
stamen 写道
对于singleton确实是这样,但对应prototype,request,session和globalSession则会多次调用,性能问题还是会有的,我觉得至少可以智能你装入属性编辑器,而不是每个BeanWrapper都有一套完整的属性编辑器,假设某个Service的Bean,它仅注入一些Dao,但这个Bean的BeanWrapper也会拥有32个默认的属性编辑器实例。
恩,确实是这样,那是否Spring的初衷是为所有的Bean的配置尽量为Singleton呢?胡乱猜测大师想法.