bean的定义,包装是java bean的基础。再怎么强调它的重要性都不为过,因此深入 了解这块的代码对以后的代码研究可以起到事半功倍的功效。
1. Bean的定义BeanDefinition
1.1 BeanDefinition 作用
一个BeanDefinition描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。BeanDefinition仅仅是一个最简单的接口,主要功能是允许BeanFactoryPostProcessor 例如PropertyPlaceHolderConfigure 能够检索并修改属性值和别的bean的元数据。
1.2 BeanDefinition的继承关系
父接口: AttributeAccessor, BeanMetadataElement 子接口: AnnotatedBeanDefinition 子类: AbstractBeanDefinition, AnnotatedGenericBeanDefinition, ChildBeanDefinition, GenericBeanDefinition, RootBeanDefinition, ScannedGenericBeanDefinition
其中,AttributeAccessor接口定义了最基本的对任意对象的元数据的修改或者获取,主要方法有:
String[] attributeNames() Object getAttribute(String name) boolean hasAttribute(String name) Object removeAttribute(String name) void setAttribute(String name, Object value)
BeanMetadataElement接口提供了一个getResource()方法,用来传输一个可配置的源对象。
1.3 BeanDefinition的抽象类AbstractBeanDefinition
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable { }
其中,BeanMetadataAttributeAccessor接口既实现了BeanMetadataElement接口提供的getResource()方法也提供了AttributeAccessorSupport 针对属性的增删改查,如上AttributeAccessor的方法。
public class BeanMetadataAttributeAccessor extends AttributeAccessorSupport implements BeanMetadataElement { }
我们来看看一个抽象的beanDefinition 的创建涉及到哪些属性?
构造方法之一,创建一个新的默认设置的AbstractBeanDefinition,如下面代码所示,具体信息也可以参考BeanDefinitionDefaults这个类。
构造方法之二,根据构造参数值和属性参数值来创建。
/** * Create a new AbstractBeanDefinition with default settings. */ protected AbstractBeanDefinition() { this(null, null); } /** * Create a new AbstractBeanDefinition with the given * constructor argument values and property values. */ protected AbstractBeanDefinition(ConstructorArgumentValues cargs, MutablePropertyValues pvs) { setConstructorArgumentValues(cargs); setPropertyValues(pvs); }
构造方法之三是深复制一个原有的beandefinition。
/** * Create a new AbstractBeanDefinition as a deep copy of the given * bean definition. * @param original the original bean definition to copy from */ protected AbstractBeanDefinition(BeanDefinition original) { setParentName(original.getParentName()); setBeanClassName(original.getBeanClassName()); setFactoryBeanName(original.getFactoryBeanName()); setFactoryMethodName(original.getFactoryMethodName()); setScope(original.getScope()); setAbstract(original.isAbstract()); setLazyInit(original.isLazyInit()); setRole(original.getRole()); setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues())); setPropertyValues(new MutablePropertyValues(original.getPropertyValues())); setSource(original.getSource()); copyAttributesFrom(original); if (original instanceof AbstractBeanDefinition) { AbstractBeanDefinition originalAbd = (AbstractBeanDefinition) original; if (originalAbd.hasBeanClass()) { setBeanClass(originalAbd.getBeanClass()); } setAutowireMode(originalAbd.getAutowireMode()); setDependencyCheck(originalAbd.getDependencyCheck()); setDependsOn(originalAbd.getDependsOn()); setAutowireCandidate(originalAbd.isAutowireCandidate()); copyQualifiersFrom(originalAbd); setPrimary(originalAbd.isPrimary()); setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed()); setLenientConstructorResolution(originalAbd.isLenientConstructorResolution()); setInitMethodName(originalAbd.getInitMethodName()); setEnforceInitMethod(originalAbd.isEnforceInitMethod()); setDestroyMethodName(originalAbd.getDestroyMethodName()); setEnforceDestroyMethod(originalAbd.isEnforceDestroyMethod()); setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides())); setSynthetic(originalAbd.isSynthetic()); setResource(originalAbd.getResource()); } else { setResourceDescription(original.getResourceDescription()); } }
上述三个方法涉及到的接口和类有:
ConstructorArgumentValues:构造参数,保存了构造方法所有的参数值,通常作为bean definition的一部分来使用。它不仅支持类型匹配的普通参数,也支持根据参数列表中的索引位置来提供参数。提供了两个变量来保存参数:带索引的和不带索引的
public class ConstructorArgumentValues { private final Map<Integer, ValueHolder> indexedArgumentValues = new LinkedHashMap<Integer, ValueHolder>(0); private final List<ValueHolder> genericArgumentValues = new LinkedList<ValueHolder>(); }
MutablePropertyValues:PropertyValues接口的默认实现,支持对属性的简单操作,为构造方法提供深度复制和使用map获取构造的支持。
2. Bean的包装BeanWrapper
2.1 作用:提供对标准javabean的分析和操作方法:单个或者批量获取和设置属性值,获取属性描述符,查询属性的可读性和可写性等。支持属性的嵌套设置,深度没有限制。
2.2 继承关系:
public interface BeanWrapper extends ConfigurablePropertyAccessor { } public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter { }
其中,ConfigurablePropertyAccessor 接口封装了PropertyAccessor的配置方法,同时继承了PropertyEditorRegistry接口,具有了对PropertyEditor进行管理的方法。该接口的固有方法:
ConversionService getConversionService() 返回关联的ConversionService,如果存在的话。
boolean isExtractOldValueForEditor() 返回标示位。如果为true,表示当使用属性编辑器编辑一个属性的值时提取旧的属性值,如果为false,则表示不提取旧值。
void setConversionService(ConversionService conversionService) conversionservice是从spring3.0引入的,可以作为java bean 属性编辑器的替代功能,作用是改变属性的值。
void setExtractOldValueForEditor(boolean extractOldValueForEditor) 设置是否提取旧的属性值标示位,如上描述。
另外,ConfigurablePropertyAccessor 接口继承的方法有:
从PropertyAccessor继承的方法有:getPropertyType, getPropertyTypeDescriptor, getPropertyValue, isReadableProperty, isWritableProperty, setPropertyValue, setPropertyValue, setPropertyValues, setPropertyValues, setPropertyValues, setPropertyValues;
从PropertyEditorRegistry继承的方法有:findCustomEditor, registerCustomEditor, registerCustomEditor;
从TypeConverter 继承的方法有:convertIfNecessary, convertIfNecessary, convertIfNecessary 。
2.3 BeanWrapper的实现类:BeanWrapperImpl
BeanWrapperImpl作用:可以根据需求,将集合与数组的值转换到对应目标对象的集合和数组。自定义的属性编辑器通过属性编辑器的setValue,setAsText方法实现上述的转换功能。
BeanWrapperImpl 默认的PropertyEditor的实现如下:(PropertyEditorRegistrySupport.java)
private void createDefaultEditors() { this.defaultEditors = new HashMap<Class<?>, PropertyEditor>(64); // Simple editors, without parameterization capabilities. // The JDK does not contain a default editor for any of these target types. this.defaultEditors.put(Charset.class, new CharsetEditor()); this.defaultEditors.put(Class.class, new ClassEditor()); this.defaultEditors.put(Class[].class, new ClassArrayEditor()); this.defaultEditors.put(Currency.class, new CurrencyEditor()); this.defaultEditors.put(File.class, new FileEditor()); this.defaultEditors.put(InputStream.class, new InputStreamEditor()); this.defaultEditors.put(InputSource.class, new InputSourceEditor()); this.defaultEditors.put(Locale.class, new LocaleEditor()); this.defaultEditors.put(Pattern.class, new PatternEditor()); this.defaultEditors.put(Properties.class, new PropertiesEditor()); this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor()); this.defaultEditors.put(TimeZone.class, new TimeZoneEditor()); this.defaultEditors.put(URI.class, new URIEditor()); this.defaultEditors.put(URL.class, new URLEditor()); this.defaultEditors.put(UUID.class, new UUIDEditor()); if (zoneIdClass != null) { this.defaultEditors.put(zoneIdClass, new ZoneIdEditor()); } // Default instances of collection editors. // Can be overridden by registering custom instances of those as custom editors. this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class)); this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class)); this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class)); this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class)); this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class)); // Default editors for primitive arrays. this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor()); this.defaultEditors.put(char[].class, new CharArrayPropertyEditor()); // The JDK does not contain a default editor for char! this.defaultEditors.put(char.class, new CharacterEditor(false)); this.defaultEditors.put(Character.class, new CharacterEditor(true)); // Spring‘s CustomBooleanEditor accepts more flag values than the JDK‘s default editor. this.defaultEditors.put(boolean.class, new CustomBooleanEditor(false)); this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true)); // The JDK does not contain default editors for number wrapper types! // Override JDK primitive number editors with our own CustomNumberEditor. this.defaultEditors.put(byte.class, new CustomNumberEditor(Byte.class, false)); this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true)); this.defaultEditors.put(short.class, new CustomNumberEditor(Short.class, false)); this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true)); this.defaultEditors.put(int.class, new CustomNumberEditor(Integer.class, false)); this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true)); this.defaultEditors.put(long.class, new CustomNumberEditor(Long.class, false)); this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true)); this.defaultEditors.put(float.class, new CustomNumberEditor(Float.class, false)); this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true)); this.defaultEditors.put(double.class, new CustomNumberEditor(Double.class, false)); this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true)); this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true)); this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true)); // Only register config value editors if explicitly requested. if (this.configValueEditorsActive) { StringArrayPropertyEditor sae = new StringArrayPropertyEditor(); this.defaultEditors.put(String[].class, sae); this.defaultEditors.put(short[].class, sae); this.defaultEditors.put(int[].class, sae); this.defaultEditors.put(long[].class, sae); } }
其中涉及到很多编辑器,在此就不赘叙了,如有兴趣,可以自行查找。
3. 小结:
bean的定义,包装是java bean的基础。可以这么说,这一块是spring的基石。本文仅仅揭开spring 中java bean的面纱,希望能起到抛砖引玉的功能,以飨读者。