`
dylan0514sina.cn
  • 浏览: 94908 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

BeanDefinition数据流

 
阅读更多
BeanDefinition是Spring配置文件中bean定义的内存表现形式,我们先来看看bean的创建。在下图中不同的元素的解析路线用不同的颜色标注
主线部分  
  1. 实例化xmlApplicationContext
  2. 实例化XmlBeanDefinitionReader
  3. ResourceLoader定位bean文件
  4. XmlBeanDefinitionReader读入Resource
  5. DefaultBeanDefinitionDocumentReader解析Document
  6. 默认命名空间判断
  7. import元素判断
  8. alias元素判断
  9. beans元素递归
非默认bean命名空间处理,如AOP
  1. 读取多个jar包中的META-INF/spring.handlers
  2. DefaultNamespaceResolver解析spring.handlers
  3.        文件,取得元素命名空间对应的NamespaceHandler
  4. NamespaceHandler解析Element元素
  5. 根据不同的Handler会生成或ComponentDefinition或BeanDefinition
  6. 注册BeanDefinition

import元素处理部分
  1.    重复主线中的3,4,5步
alias元素处理部分
  1.    注册标志和别名
bean元素处理部分
  1.    通过BeanfinitionParserDelegate解析bean元素
  2.    注册BeanDefinitionHolder






在解析bean.xml的过程中,用"<property....."作为类的属性值,与之对应的值的定义方式不同反应不同的数据结构,

1.<property name="foo" ref="bean"/>
2.<property name="foo" value="beanString"/>
3.<property name="foo">
  <bean class=""/>
</property>
....

beanDefinition必须存储这些信息,那BeanDefinition定义中,可以看到属性值设置信息在MutablePropertyValues 中,当然<constructor-arg/>类似,存储在ConstructorArgumentValues
ConstructorArgumentValues getConstructorArgumentValues();
MutablePropertyValues getPropertyValues();

不同的Element或Attribute对应不同的属性值的结构列表如下



这些数据类型会在getBean初始化设值时转化为必要值引用类型,对于值是beanDefinitionHolder的将生成为一个prototype的bean。
public Object resolveValueIfNecessary(Object argName, Object value) {
		// We must check each value to see whether it requires a runtime reference
		// to another bean to be resolved.
		if (value instanceof RuntimeBeanReference) {
			RuntimeBeanReference ref = (RuntimeBeanReference) value;
			return resolveReference(argName, ref);
		}
		else if (value instanceof RuntimeBeanNameReference) {
			String refName = ((RuntimeBeanNameReference) value).getBeanName();
			refName = String.valueOf(evaluate(refName));
			if (!this.beanFactory.containsBean(refName)) {
				throw new BeanDefinitionStoreException(
						"Invalid bean name '" + refName + "' in bean reference for " + argName);
			}
			return refName;
		}
		else if (value instanceof BeanDefinitionHolder) {
			// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
			BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
			return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
		}
		else if (value instanceof BeanDefinition) {
			// Resolve plain BeanDefinition, without contained name: use dummy name.
			BeanDefinition bd = (BeanDefinition) value;
			return resolveInnerBean(argName, "(inner bean)", bd);
		}
		else if (value instanceof ManagedArray) {
			// May need to resolve contained runtime references.
			ManagedArray array = (ManagedArray) value;
			Class elementType = array.resolvedElementType;
			if (elementType == null) {
				String elementTypeName = array.getElementTypeName();
				if (StringUtils.hasText(elementTypeName)) {
					try {
						elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
						array.resolvedElementType = elementType;
					}
					catch (Throwable ex) {
						// Improve the message by showing the context.
						throw new BeanCreationException(
								this.beanDefinition.getResourceDescription(), this.beanName,
								"Error resolving array type for " + argName, ex);
					}
				}
				else {
					elementType = Object.class;
				}
			}
			return resolveManagedArray(argName, (List<?>) value, elementType);
		}
		else if (value instanceof ManagedList) {
			// May need to resolve contained runtime references.
			return resolveManagedList(argName, (List<?>) value);
		}
		else if (value instanceof ManagedSet) {
			// May need to resolve contained runtime references.
			return resolveManagedSet(argName, (Set<?>) value);
		}
		else if (value instanceof ManagedMap) {
			// May need to resolve contained runtime references.
			return resolveManagedMap(argName, (Map<?, ?>) value);
		}
		else if (value instanceof ManagedProperties) {
			Properties original = (Properties) value;
			Properties copy = new Properties();
			for (Map.Entry propEntry : original.entrySet()) {
				Object propKey = propEntry.getKey();
				Object propValue = propEntry.getValue();
				if (propKey instanceof TypedStringValue) {
					propKey = evaluate((TypedStringValue) propKey);
				}
				if (propValue instanceof TypedStringValue) {
					propValue = evaluate((TypedStringValue) propValue);
				}
				copy.put(propKey, propValue);
			}
			return copy;
		}
		else if (value instanceof TypedStringValue) {
			// Convert value to target type here.
			TypedStringValue typedStringValue = (TypedStringValue) value;
			Object valueObject = evaluate(typedStringValue);
			try {
				Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
				if (resolvedTargetType != null) {
					return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
				}
				else {
					return valueObject;
				}
			}
			catch (Throwable ex) {
				// Improve the message by showing the context.
				throw new BeanCreationException(
						this.beanDefinition.getResourceDescription(), this.beanName,
						"Error converting typed String value for " + argName, ex);
			}
		}
		else {
			return evaluate(value);
		}
	}

转化规则如下

当实例都准备好之后,在匹配之前支持做类型转换
Spring使用java bean规范中的PropertyEditors解决中Object和String之间的转换 。我们可以自定义java.beans.PropertyEditor实现,然后注册到Spring容器中。比如经常使用的场景是解析bean.xml时。org.springframework.beans.propertyeditors包下的所有编辑器被Spring支持,Spring通过java.bean.PropertyEditorManager设置这种搜索路径。经典实现中,将会查找class bean包路径+"Editor"


Foo类同包下面有个FooEditor
com
  chank
    pop
      Foo
      FooEditor   // the PropertyEditor for the Foo class

在使用JAVA BEAN自省机制之前,可以定义Foo类的BeanInfo
com
  chank
    pop
      Foo
      FooBeanInfo   // the BeanInfo for the Foo class
public class FooBeanInfo extends SimpleBeanInfo {

    public PropertyDescriptor[] getPropertyDescriptors() {
        try {
            final PropertyEditor numberPE = new CustomNumberEditor(Integer.class, true);
            PropertyDescriptor ageDescriptor = new PropertyDescriptor("age", Foo.class) {
                public PropertyEditor createPropertyEditor(Object bean) {
                    return numberPE;
                };
            };
            return new PropertyDescriptor[] { ageDescriptor };
        }
        catch (IntrospectionException ex) {
            throw new Error(ex.toString());
        }
    }
}

接下来进行注册
将ExoticType 实例注入到DependsOnExoticType 中,很显然,我们需要
ExoticType对应的Editor将字符串转化为ExoticType 以注入

package example;

public class ExoticType {

    private String name;

    public ExoticType(String name) {
        this.name = name;
    }
}

public class DependsOnExoticType {

    private ExoticType type;

    public void setType(ExoticType type) {
        this.type = type;
    }
}

只是一个ExoticType 名字
<bean id="sample" class="example.DependsOnExoticType">
    <property name="type" value="aNameForExoticType"/>
</bean>

PropertyEditor实现
// converts string representation to ExoticType object
package example;

public class ExoticTypeEditor extends PropertyEditorSupport {

    public void setAsText(String text) {
        setValue(new ExoticType(text.toUpperCase()));
    }
}

我们将使用CustomEditorConfigurer注册,这是一个BeanFactoryPostProcessor Bean,在ApplicationContext生命周期中自动调用
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
  <property name="customEditors">
    <map>
      <entry key="example.ExoticType" value="example.ExoticTypeEditor"/>
    </map>
  </property>
</bean>

如果要使用多个Editor,则还可以实现PropertyEditorRegistrar 接口,在实现中编程注册;显然多了一层包装。
public final class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {

    public void registerCustomEditors(PropertyEditorRegistry registry) {

        // it is expected that new PropertyEditor instances are created
        registry.registerCustomEditor(ExoticType.class, new ExoticTypeEditor());

        // you could register as many custom property editors as are required here...
    }
}

<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name="propertyEditorRegistrars">
        <list>
            <ref bean="customPropertyEditorRegistrar"/>
        </list>
    </property>
</bean>

<bean id="customPropertyEditorRegistrar"
      class="com.foo.editors.spring.CustomPropertyEditorRegistrar"/>

java bean风格的类型转化只在String与Object之间,那如果Object和Object,则java bean标准转化机制显得不够用。spring 3引入了core.convert包提供更加一般化的类型转换。使用泛型机制,强制类型。
public interface Converter<S, T> {

    T convert(S source);

}
//简单实现StringToInteger 
final class StringToInteger implements Converter<String, Integer> {

    public Integer convert(String source) {
        return Integer.valueOf(source);
    }

}

当仅仅关注某一类型的转化器时,ConverterFactory有了用武之地。
public interface ConverterFactory<S, R> {

    <T extends R> Converter<S, T> getConverter(Class<T> targetType);

}
//将字符串转化为一个枚举类型的factory
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {

    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnumConverter(targetType);
    }

    private final class StringToEnumConverter<T extends Enum> implements Converter<String, T> {

        private Class<T> enumType;

        public StringToEnumConverter(Class<T> enumType) {
            this.enumType = enumType;
        }

        public T convert(String source) {
            return (T) Enum.valueOf(this.enumType, source.trim());
        }
    }
}

GenericConverter没有泛型化
package org.springframework.core.convert.converter;

public interface GenericConverter {

    public Set<ConvertiblePair> getConvertibleTypes();

    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);

}

ConditionalGenericConverter想执行转换之前知道是否能够转换
public interface ConditionalGenericConverter extends GenericConverter {

    boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);

}

ConversionService 实现具体的转换逻辑。spring中大多数现象了
ConversionService 的同时也实现了ConverterRegistry,ConverterRegistry用于注册转换器,一般来说,ConversionService 实现需要使用转换器了解源对象和目标对象的类型。GenericConversionService就是这样的一个实现。
package org.springframework.core.convert;

public interface ConversionService {

    boolean canConvert(Class<?> sourceType, Class<?> targetType);

    <T> T convert(Object source, Class<T> targetType);

    boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);

    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);

}

我们将使用ConversionServiceFactoryBean注册转换器和GenericConversionService
<bean id="conversionService"
      class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="example.MyCustomConverter"/>
        </list>
    </property>
</bean>
  • 大小: 38.4 KB
  • 大小: 42.9 KB
  • 大小: 59.2 KB
  • 大小: 51.5 KB
  • 大小: 63.3 KB
  • 大小: 39.3 KB
  • 大小: 64 KB
  • 大小: 74.2 KB
  • 大小: 250.5 KB
分享到:
评论

相关推荐

    XmlBean 使用说明及jar包

    - **类型安全的 XML 解析**:XmlBean 将 XML 文档映射为 Java 类,允许开发者以面向对象的方式处理 XML 数据,避免了字符串操作的错误。 - **XML Schema 支持**:XmlBean 基于 XML Schema 来生成 Java 类,这使得 ...

    spring 源码二

    BeanDefinition则是bean的元数据,存储了关于bean如何被创建和初始化的所有信息。 Spring源码中广泛应用了设计模式,如工厂模式(BeanFactory)、单例模式(Singleton)、代理模式(AOP代理)、装饰器模式...

    Spring源码学习一:源码分析概述1

    1. Spring的核心组件:包括BeanFactory、ApplicationContext、BeanDefinition等。 2. Spring的依赖注入机制:包括依赖注入的原理、实现机制和应用场景。 3. Spring的AOP机制:包括AOP的原理、实现机制和应用场景。 4...

    spring 开发手册(pdf)

    3. **BeanDefinition**:这是描述一个Bean的元数据,包括Bean的类、构造函数参数、属性值、作用域等。BeanDefinition在Spring配置文件或注解中定义,是Spring容器创建Bean的基础。 三、依赖注入与Bean的配置 依赖...

    spring ioc

    1. `BeanDefinition`:每个 Bean 在容器中都有一个对应的 `BeanDefinition`,它存储了 Bean 的所有元数据,如类名、初始化方法、依赖等。 2. `BeanFactory`:这是最基础的 Bean 容器接口,负责创建和管理 Bean。 3. ...

    spring常用包

    2. **spring-beans**:这个模块定义了Spring IoC容器的基本元素,包括BeanDefinition和FactoryBean。BeanDefinition存储了关于Bean的所有元信息,如类名、属性、依赖等。FactoryBean用于创建特殊的Bean,它可以返回...

    spring-framework-reference 3.0

    Bean Definition Profiles 允许开发者根据不同的环境配置不同的Bean属性,这对于多环境的应用程序来说是非常有用的。 ##### 3. Environment Abstraction 环境抽象提供了一种机制,让开发者能够在不同的环境中使用...

    activiti工作流demo

    - **配置文件(如applicationContext.xml)**:配置Spring容器,声明Activiti的bean,如流程引擎、数据源、事务管理器等。 - **测试类**:演示如何使用代码来操作流程,比如启动流程实例,查询当前用户的任务,完成...

    基于SSH框架的Web网站设计与实现.doc

    Spring框架的主要组件包括BeanFactory、ApplicationContext、BeanDefinition等。 最后,SSH框架的持久层是指使用Hibernate框架来实现数据持久化。Hibernate框架是一个 ORM(Object-Relational Mapping)工具,它...

    spring4 文档

    Spring资源抽象层是一个灵活的接口,可以读取来自不同源的数据流。Spring提供多种资源实现,包括文件系统资源、classpath资源和URL资源等。 **验证、数据绑定和类型转换** Spring提供了一套验证框架,允许开发者...

    Object-XML文件的相互转换分析

    Spring的`BeanDefinition`接口是连接XML配置和实际对象的关键,它代表了一个bean的完整定义,包括其类、属性值、依赖关系等。`DefaultListableBeanFactory`使用`XmlBeanDefinitionReader`从XML文件加载bean定义,...

    迭代器模式

    例如,Spring框架中的`org.springframework.beans.FatalBeanException`类在初始化Bean时会遍历BeanDefinition的属性,这里就使用了迭代器。另外,Apache Commons Collections库提供了丰富的迭代器实现,帮助开发者...

    activiti工作流引擎

    1. 流程定义(Process Definition):流程定义是Activiti的核心,它用BPMN 2.0标准的XML格式描述了一个业务流程。BPMN提供了丰富的图形符号,如开始事件、结束事件、用户任务、服务任务等,帮助开发者直观地设计流程...

    工作流的--基础概念

    接口的设计和实现取决于具体工作流产品,可能包括对Java Bean、Web服务、XML Bean和Spring Bean的调用。 3. **任务管理工具**:管理流程中的任务分配,为用户提供待办事项列表,确保任务的正确执行。这些工具通常...

    spring-framework-reference.pdf

    - **Groovy Bean Definition DSL(Groovy Bean Definition DSL)**:引入了使用Groovy语言定义Bean的新方式。 - **核心容器改进(Core Container Improvements)**:增强了核心容器的功能。 - **通用Web改进(General Web...

    最新spring官网文档英文(4.3.0.RC1)

    Groovy Bean Definition DSL是一种使用Groovy语言定义Spring Bean的新方法,使得配置更加简洁和灵活。 **3.6 核心容器改进** 对Spring的核心容器进行了优化,提高了性能并增强了功能性。 **3.7 Web改进** 对Web...

    spring4.0库

    它还包含BeanDefinition,用于存储Bean的元数据,以及BeanFactory和AbstractApplicationContext,是Spring IoC容器的基础。 4. **spring-web-4.0.0.RELEASE.jar**:该模块是Spring框架的Web支持部分,提供了与...

    spring3.0.6官方jar包

    2. `org.springframework.beans-3.0.6.RELEASE.jar`: 这个模块包含用于处理Java Bean的工具类和接口,如BeanDefinition和BeanWrapper,它们是Spring管理bean的基础,支持属性注入、类型转换和bean的生命周期管理。...

    spring-framework-4-reference 中文文档

    - **Groovy Bean Definition DSL**:提供了 Groovy 语言编写配置文件的支持。 - **核心容器改进**:增强了 Bean 的生命周期管理,引入了新的 API。 - **Web 改进**:增强了 MVC 和 WebSocket 的支持。 - **...

Global site tag (gtag.js) - Google Analytics