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的面紗,但願能起到拋磚引玉的功能,以饗讀者。