bean的定义,包装是java bean的基础。再怎么强调它的重要性都不为过,所以深刻 了解这块的代码对之后的代码研究能够起到事半功倍的功效。java
1. Bean的定义BeanDefinitionspring
1.1 BeanDefinition 做用数组
一个BeanDefinition描述了一个bean的实例,包括属性值,构造方法参数值和继承自它的类的更多信息。BeanDefinition仅仅是一个最简单的接口,主要功能是容许BeanFactoryPostProcessor 例如PropertyPlaceHolderConfigure 可以检索并修改属性值和别的bean的元数据。app
1.2 BeanDefinition的继承关系编辑器
父接口:
AttributeAccessor, BeanMetadataElement
子接口:
AnnotatedBeanDefinition
子类:
AbstractBeanDefinition, AnnotatedGenericBeanDefinition, ChildBeanDefinition, GenericBeanDefinition, RootBeanDefinition, ScannedGenericBeanDefinition
其中,AttributeAccessor接口定义了最基本的对任意对象的元数据的修改或者获取,主要方法有:ide
String[] attributeNames() Object getAttribute(String name) boolean hasAttribute(String name) Object removeAttribute(String name) void setAttribute(String name, Object value)
BeanMetadataElement接口提供了一个getResource()方法,用来传输一个可配置的源对象。post
1.3 BeanDefinition的抽象类AbstractBeanDefinitionthis
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor implements BeanDefinition, Cloneable { }
其中,BeanMetadataAttributeAccessor接口既实现了BeanMetadataElement接口提供的getResource()方法也提供了AttributeAccessorSupport 针对属性的增删改查,如上AttributeAccessor的方法。编码
public class BeanMetadataAttributeAccessor extends AttributeAccessorSupport implements BeanMetadataElement { }
咱们来看看一个抽象的beanDefinition 的建立涉及到哪些属性?spa
构造方法之一,建立一个新的默认设置的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获取构造的支持。
1.4 bean definition实现类ChildBeanDefinition, GenericBeanDefinition, RootBeanDefinition
1.4.1 ChildBeanDefinition是一种bean definition,它能够继承它父类的设置,即ChildBeanDefinition对RootBeanDefinition有必定的依赖关系。
ChildBeanDefinition从父类继承构造参数值,属性值并能够重写父类的方法,同时也能够增长新的属性或者方法。(类同于java类的继承关系)。若指定初始化方法,销毁方法或者静态工厂方法, ChildBeanDefinition将重写相应父类的设置。depends on,autowire mode,dependency check,sigleton,lazy init 通常由子类自行设定。
注意:从spring 2.5 开始,提供了一个更好的注册bean definition类GenericBeanDefinition,它支持动态定义父依赖,方法是GenericBeanDefinition.setParentName(java.lang.String),GenericBeanDefinition能够有效的替代ChildBeanDefinition的绝大分部使用场合。
1.4.2 GenericBeanDefinition是一站式的标准bean definition,除了具备指定类、可选的构造参数值和属性参数这些其它bean definition同样的特性外,它还具备经过parenetName属性来灵活设置parent bean definition。
一般, GenericBeanDefinition用来注册用户可见的bean definition(可见的bean definition意味着能够在该类bean definition上定义post-processor来对bean进行操做,甚至为配置parent name作扩展准备)。RootBeanDefinition
/ ChildBeanDefinition用来预约义具备
parent/child关系的bean definition。
1.4.3 RootBeanDefinition
一个RootBeanDefinition定义代表它是一个可合并的bean definition:即在spring beanFactory运行期间,能够返回一个特定的bean。RootBeanDefinition能够做为一个重要的通用的bean definition 视图。
RootBeanDefinition用来在配置阶段进行注册bean definition。而后,从spring 2.5后,编写注册bean definition有了更好的的方法:GenericBeanDefinition。GenericBeanDefinition支持动态定义父类依赖,而非硬编码做为root bean definition。
涉及到的类:BeanDefinitionHolder,根据名称或者别名持有beanDefinition。能够为一个内部bean 注册为placeholder。
BeanDefinitionHolder也能够编写一个内部bean definition的注册,若是你不关注BeanNameAware等,彻底可使用RootBeanDefinition或者ChildBeanDefinition来替代。
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的面纱,但愿能起到抛砖引玉的功能,以飨读者。