参考文章:
实例化 Bean 阶段,我们从 BeanDefinition 得到的并不是我们最终想要的 Bean 实例,而是 BeanWrapper
BeanWrapper 是 Spring 框架中重要的组件类,它就相当于一个代理类,Spring 委托 BeanWrapper 完成 Bean 属性的填充工作。在 Bean 实例被 InstantiationStrategy 创建出来后,Spring 容器会将 Bean 实例通过 BeanWrapper 包裹起来
//AbstractAutowireCapableBeanFactory.java.doCreateBean
BeanWrapper instanceWrapper = null;
// 单例模型,则从未完成的 FactoryBean 缓存中删除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 包装的实例对象
final Object bean = instanceWrapper.getWrappedInstance();
// 包装的实例对象的class
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
BeanWrapper接口关系
根据查看BeanWrapper的关系为
其主要的核心接口为
- PropertyAccessor
- TypeConverter
- PropertyEditorRegistry
这三个接口主要的作用
BeanWrapper 继承上述三个接口,那么它就具有三重身份:
- 属性编辑器
- 属性编辑器注册表
- 类型转换器
ConfigurablePropertyAccessor
BeanWrapper 同时继承 ConfigurablePropertyAccessor,其做了一些额外的扩展
由于 TypeConverter 是基于线程不安全的 PropertyEditors ,因此 TypeConverters 本身也不被视为线程安全,在 Spring 3 后,不在采用 PropertyEditors 类作为 Spring 默认的类型转换接口,而是采用 ConversionService 体系,但 ConversionService 是线程安全的,所以在 Spring 3 后,如果你所选择的类型转换器是 ConversionService 而不是 PropertyEditors 那么 TypeConverters 则是线程安全的
public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter {
/**
* 指定用于转换属性值的Spring3.0 ConversionService,作为JavaBeans属性编辑器的替代方法。
*/
void setConversionService(@Nullable ConversionService conversionService);
/**
* 返回关联的ConversionService(如果有)
*/
@Nullable
ConversionService getConversionService();
/**
*
* 设置在将属性编辑器应用于属性的新值时是否提取旧属性值
*/
void setExtractOldValueForEditor(boolean extractOldValueForEditor);
/**
* 返回在将属性编辑器应用于属性的新值时是否提取旧属性值。
*/
boolean isExtractOldValueForEditor();
/**
* Set whether this instance should attempt to "auto-grow" a
* nested path that contains a {@code null} value.
* <p>If {@code true}, a {@code null} path location will be populated
* with a default object value and traversed instead of resulting in a
* {@link NullValueInNestedPathException}.
* <p>Default is {@code false} on a plain PropertyAccessor instance.
*/
void setAutoGrowNestedPaths(boolean autoGrowNestedPaths);
/**
* Return whether "auto-growing" of nested paths has been activated.
*/
boolean isAutoGrowNestedPaths();
}