文前说明
作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。
本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。
1. 概述
- 实例化 Bean 阶段,从
BeanDefinition
得到的是BeanWrapper
实例,是一个从BeanDefinition
到 Bean 的中间对象,一般情况下,不会在实际项目中用到它。 -
BeanWrapper
是 Spring 框架中重要的组件类,相当于一个代理类。 - 在 Bean 实例被
InstantiationStrategy
创建出来后,Spring 容器会将 Bean 实例通过BeanWrapper
包裹。
2. 原理
// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
......
// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
Class> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
} else if (mbd.getFactoryMethodName() != null) {
return this.instantiateUsingFactoryMethod(beanName, mbd, args);
} else {
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized(mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
} else {
Constructor>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args) ? this.instantiateBean(beanName, mbd) : this.autowireConstructor(beanName, mbd, ctors, args);
}
}
}
// AbstractAutowireCapableBeanFactory.java
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(new PrivilegedAction
-
BeanWrapper
主要继承三个核心接口PropertyAccessor
、PropertyEditorRegistry
和TypeConverter
。
PropertyAccessor
- 可以访问属性的通用型接口(例如对象的 bean 属性或者对象中的字段),作为
BeanWrapper
的基础接口。
// PropertyAccessor.java
public interface PropertyAccessor {
String NESTED_PROPERTY_SEPARATOR = ".";
char NESTED_PROPERTY_SEPARATOR_CHAR = '.';
String PROPERTY_KEY_PREFIX = "[";
char PROPERTY_KEY_PREFIX_CHAR = '[';
String PROPERTY_KEY_SUFFIX = "]";
char PROPERTY_KEY_SUFFIX_CHAR = ']';
boolean isReadableProperty(String propertyName);
boolean isWritableProperty(String propertyName);
Class> getPropertyType(String propertyName) throws BeansException;
TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException;
Object getPropertyValue(String propertyName) throws BeansException;
void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException;
void setPropertyValue(PropertyValue pv) throws BeansException;
void setPropertyValues(Map, ?> map) throws BeansException;
void setPropertyValues(PropertyValues pvs) throws BeansException;
void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown)
throws BeansException;
void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid)
throws BeansException;
}
- 主要分为 4 类方法。
方法 | 说明 |
---|---|
isReadableProperty() | 判断指定 property 是否可读,是否包含 getter 方法。 |
isWritableProperty() | 判断指定 property 是否可写,是否包含 setter 方法。 |
getPropertyType() | 获取指定 propertyName 的类型。 |
setPropertyValue() | 设置指定 propertyValue。 |
PropertyEditorRegistry
- 用于注册 JavaBean 的
PropertyEditors
,对PropertyEditorRegistrar
起核心作用的中心接口。由BeanWrapper
扩展,BeanWrapperImpl
和DataBinder
实现。
// PropertyEditorRegistry.java
public interface PropertyEditorRegistry {
void registerCustomEditor(Class> requiredType, PropertyEditor propertyEditor);
void registerCustomEditor(@Nullable Class> requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor);
@Nullable
PropertyEditor findCustomEditor(@Nullable Class> requiredType, @Nullable String propertyPath);
}
- 根据接口提供的方法,
PropertyEditorRegistry
用于PropertyEditor
的注册和发现,PropertyEditor
是 Java 内省接口,用于改变指定 property 属性的类型。
TypeConverter
- 定义类型转换的接口,通常与
PropertyEditorRegistry
接口一起实现(但不是必须) - Spring 3 后,不再采用
PropertyEditors
类作为 Spring 默认的类型转换接口,而是采用ConversionService
体系。-
ConversionService
是线程安全的,所以在 Spring 3 后,如果选择的类型转换器是ConversionService
那么TypeConverters
是线程安全的。 - 如果选择的是
PropertyEditors
,则是线程不安全的。
-
// TypeConverter.java
public interface TypeConverter {
T convertIfNecessary(Object value, Class requiredType) throws TypeMismatchException;
T convertIfNecessary(Object value, Class requiredType, MethodParameter methodParam)
throws TypeMismatchException;
T convertIfNecessary(Object value, Class requiredType, Field field)
throws TypeMismatchException;
}
- BeanWrapper 继承了上述三个接口,所以可以作为 属性编辑器、属性编辑器注册表、类型转换器 使用。
-
BeanWrapper
除了继承ConfigurablePropertyAccessor
接口以外,还集成了 Spring 的ConversionService
类型转换体系。
// ConfigurablePropertyAccessor.java
public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter {
void setConversionService(@Nullable ConversionService conversionService);
@Nullable
ConversionService getConversionService();
......
}
BeanWrapper
- 一般不会直接使用,而是通过
BeanFactory
或者DataBinder
隐式使用。 - 它提供分析和操作标准 JavaBeans 的操作:获取和设置属性值、获取属性描述符以及查询属性的可读性/可写性的能力。
// BeanWrapper.java
public interface BeanWrapper extends ConfigurablePropertyAccessor {
void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
int getAutoGrowCollectionLimit();
Object getWrappedInstance();
Class> getWrappedClass();
PropertyDescriptor[] getPropertyDescriptors();
PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
}
方法 | 说明 |
---|---|
getWrappedInstance() | 获取包装对象的实例。 |
getWrappedClass() | 获取包装对象的类型。 |
getPropertyDescriptors() | 获取包装对象所有属性的 PropertyDescriptor 就是这个属性的上下文。 |
getPropertyDescriptor(String propertyName) | 获取包装对象指定属性的上下文。 |
BeanWrapperImpl
-
BeanWrapper
接口的默认实现,用于对 Bean 的包装,实现接口所定义的功能。