Spring 系列目錄(http://www.javashuo.com/article/p-hskusway-em.html)html
BeanWrapper 位於 org.springframework.beans 包中,默認實現爲 BeanWrapperImpl,提供分析和處理標準 JavaBean 用於 get 和 set 屬性,取得屬性描述,查詢屬性的讀/寫能力。java
beans 包還提供了一個 PropertyValues 用於保存多個屬性值,默認的實現 MutablePropertyValues。另外還有兩個有用的工具類,BeanUtils 和 PropertyAccessorUtils。spring
PropertyEditorRegistry
PropertyEditor 註冊、查找。TypeConverter
類型轉換,其主要的工做由 TypeConverterDelegate 這個類完成的。PropertyAccessor
屬性讀寫。ConfigurablePropertyAccessor
配置一些屬性,如設置 ConversionService、是否暴露舊值、嵌套注入時屬性爲 null 是否自動建立。BeanWrapper
對 bean 進行封裝。AbstractNestablePropertyAccessor
實現了對嵌套屬性注入的處理,其它實現見名知義就不介紹了。BeanWrapper 的層次結構仍是比較清晰的,繼承於 ConfigurablePropertyAccessor 和 PropertyAccessor 接口。數組
有一點不太明白,爲何 BeanWrapper 要繼承於 PropertyEditorRegistry。從字面意義上來講,PropertyEditorRegistry 提供了 PropertyEditor,而 TypeConverter 進行類型轉換,和 BeanWrapper 不是繼承關係,使用組合感受更好。app
PropertyEditor 將 String 轉換爲其它類型,PropertyEditorRegistry 統一管理全部的 PropertyEditor 註冊和查找。編輯器
public interface PropertyEditorRegistry { // 1. 根據類型註冊 PropertyEditor void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor); // 2. 根據類型(requiredType)和屬性(propertyPath)註冊 PropertyEditor // 查找時優先根據 propertyPath 查找對應的 PropertyEditor,propertyPath 能夠爲嵌套屬性 void registerCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor); // 3. 根據類型和屬性查找 PropertyEditor PropertyEditor findCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath); }
PropertyEditorRegistry 的實現類 PropertyEditorRegistrySupport 分析見這兩篇文章:ide
TypeConverter 負責類型轉換,其主要的工做由 TypeConverterDelegate 這個類完成的。工具
public interface TypeConverter { // 1. value 轉換成 requiredType <T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException; // 2. methodParam 同下 <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam) throws TypeMismatchException; // 3. field 是 value 轉換成 requiredType 後須要賦值的 field 字段 // 能夠從該 field 字段拿到其泛型信息,從而進一步判斷是否能夠轉換,畢竟 requiredType 只有 Class 信息 <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field) throws TypeMismatchException; }
TypeConverter 的實現類 TypeConverterSupport 的全部功能,實際是都是委託給 TypeConverterDelegate 完成的。源碼分析
PropertyAccessor 提供了對 JavaBean 的基本操做。ui
public interface PropertyAccessor { 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; }
PropertyAccessor 的實現類是 AbstractPropertyAccessor,這個類中 setPropertyValue 進行了處理,最終都是調用 setPropertyValue(String propertyName, Object value) 完成屬性注入。
public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter { void setConversionService(@Nullable ConversionService conversionService); ConversionService getConversionService(); // PropertyEditor 使用時是否暴露修改先後值 void setExtractOldValueForEditor(boolean extractOldValueForEditor); boolean isExtractOldValueForEditor(); // 嵌套注入時當屬性爲 null 時是否自動生成對象 void setAutoGrowNestedPaths(boolean autoGrowNestedPaths); boolean isAutoGrowNestedPaths(); }
ConfigurablePropertyAccessor 的實現也類是 AbstractPropertyAccessor,這個類中默認 extractOldValueForEditor 和 autoGrowNestedPaths 都是 false,即不暴露舊值,也不支持嵌套注入時屬性爲 null 就自動建立對象。
public interface BeanWrapper extends ConfigurablePropertyAccessor { // @since 4.1 設置集合或數組自動生成對象的最大嵌套深度 void setAutoGrowCollectionLimit(int autoGrowCollectionLimit); int getAutoGrowCollectionLimit(); Object getWrappedInstance(); Class<?> getWrappedClass(); PropertyDescriptor[] getPropertyDescriptors(); PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException; }
BeanWrapper 的實現類是 BeanWrapperImpl,主要完成了 JavaBean 的內省,包括 PropertyDescriptor 的獲取,屬性的賦值等。
(1) JavaBean 的內省
private CachedIntrospectionResults cachedIntrospectionResults; // 獲取 private CachedIntrospectionResults getCachedIntrospectionResults() { if (this.cachedIntrospectionResults == null) { this.cachedIntrospectionResults = CachedIntrospectionResults.forClass(getWrappedClass()); } return this.cachedIntrospectionResults; }
JavaBean 的內省都是由 CachedIntrospectionResults 完成,經過 cachedIntrospectionResults 就能夠獲取對應屬性的 PropertyDescriptor。例以下面兩個方法:
@Override public PropertyDescriptor[] getPropertyDescriptors() { return getCachedIntrospectionResults().getPropertyDescriptors(); } @Override public PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException { BeanWrapperImpl nestedBw = (BeanWrapperImpl) getPropertyAccessorForPropertyPath(propertyName); // 獲取屬性名稱 String finalPath = getFinalPath(nestedBw, propertyName); PropertyDescriptor pd = nestedBw.getCachedIntrospectionResults().getPropertyDescriptor(finalPath); return pd; }
(2) BeanPropertyHandler
@Override protected BeanPropertyHandler getLocalPropertyHandler(String propertyName) { PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName); return (pd != null ? new BeanPropertyHandler(pd) : null); }
BeanPropertyHandler 是 BeanWrapperImpl 的內部類,是對 PropertyDescriptor 的封裝,完成對屬性的各類操做,如賦值。
(3) convertForProperty
convertForProperty 在 AbstractAutowireCapableBeanFactory#applyPropertyValues 屬性注入時使用
public Object convertForProperty(@Nullable Object value, String propertyName) throws TypeMismatchException { CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults(); PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName); if (pd == null) { throw new InvalidPropertyException(getRootClass(), getNestedPath() + propertyName, "No property '" + propertyName + "' found"); } TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd); if (td == null) { td = cachedIntrospectionResults.addTypeDescriptor(pd, new TypeDescriptor(property(pd))); } // 父類 AbstractNestablePropertyAccessor 進行類型轉換 return convertForProperty(propertyName, null, value, td); } // Property 也是對 PropertyDescriptor 封裝,在 Android 等環境中不存在 PropertyDescriptor 類 private Property property(PropertyDescriptor pd) { GenericTypeAwarePropertyDescriptor gpd = (GenericTypeAwarePropertyDescriptor) pd; return new Property(gpd.getBeanClass(), gpd.getReadMethod(), gpd.getWriteMethod(), gpd.getName()); }
天天用心記錄一點點。內容也許不重要,但習慣很重要!