日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

spring beans源码解读之--Bean的定义及包装

發布時間:2025/4/5 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring beans源码解读之--Bean的定义及包装 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??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 BeanMetadataAttributeAccessorimplements 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獲取構造的支持。

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

?

轉載于:https://www.cnblogs.com/davidwang456/p/4192318.html

總結

以上是生活随笔為你收集整理的spring beans源码解读之--Bean的定义及包装的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。