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

本文内容纲要: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 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获取构造的支持。

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来替代。

  1. 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);

}

}

其中涉及到很多编辑器,在此就不赘叙了,如有兴趣,可以自行查找。

  1. 小结:

bean的定义,包装是java bean的基础。可以这么说,这一块是spring的基石。本文仅仅揭开spring 中java bean的面纱,希望能起到抛砖引玉的功能,以飨读者。

本文内容总结:spring beans源码解读之--Bean的定义及包装

原文链接:https://www.cnblogs.com/davidwang456/p/4192318.html

以上是 spring beans源码解读之--Bean的定义及包装 的全部内容, 来源链接: utcz.com/z/362329.html

回到顶部