- 浏览: 94908 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
dylan0514sina.cn:
youjianbo_han_87 写道dylan0514sin ...
方法缓存 -
youjianbo_han_87:
dylan0514sina.cn 写道youjianbo_ha ...
方法缓存 -
dylan0514sina.cn:
youjianbo_han_87 写道缓存方法有意义吗,方法+ ...
方法缓存 -
youjianbo_han_87:
缓存方法有意义吗,方法+调用从缓存中取内容的方法 换成 方法+ ...
方法缓存 -
dylan0514sina.cn:
Shen.Yiyang 写道剔除策略只有方法执行的时候指定ke ...
方法缓存
BeanDefinition是Spring配置文件中bean定义的内存表现形式,我们先来看看bean的创建。在下图中不同的元素的解析路线用不同的颜色标注
主线部分
import元素处理部分
在解析bean.xml的过程中,用"<property....."作为类的属性值,与之对应的值的定义方式不同反应不同的数据结构,
beanDefinition必须存储这些信息,那BeanDefinition定义中,可以看到属性值设置信息在MutablePropertyValues 中,当然<constructor-arg/>类似,存储在ConstructorArgumentValues
不同的Element或Attribute对应不同的属性值的结构列表如下
这些数据类型会在getBean初始化设值时转化为必要值引用类型,对于值是beanDefinitionHolder的将生成为一个prototype的bean。
转化规则如下
当实例都准备好之后,在匹配之前支持做类型转换
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
在使用JAVA BEAN自省机制之前,可以定义Foo类的BeanInfo
接下来进行注册
将ExoticType 实例注入到DependsOnExoticType 中,很显然,我们需要
ExoticType对应的Editor将字符串转化为ExoticType 以注入
只是一个ExoticType 名字
PropertyEditor实现
我们将使用CustomEditorConfigurer注册,这是一个BeanFactoryPostProcessor Bean,在ApplicationContext生命周期中自动调用
如果要使用多个Editor,则还可以实现PropertyEditorRegistrar 接口,在实现中编程注册;显然多了一层包装。
java bean风格的类型转化只在String与Object之间,那如果Object和Object,则java bean标准转化机制显得不够用。spring 3引入了core.convert包提供更加一般化的类型转换。使用泛型机制,强制类型。
当仅仅关注某一类型的转化器时,ConverterFactory有了用武之地。
GenericConverter没有泛型化
ConditionalGenericConverter想执行转换之前知道是否能够转换
ConversionService 实现具体的转换逻辑。spring中大多数现象了
ConversionService 的同时也实现了ConverterRegistry,ConverterRegistry用于注册转换器,一般来说,ConversionService 实现需要使用转换器了解源对象和目标对象的类型。GenericConversionService就是这样的一个实现。
我们将使用ConversionServiceFactoryBean注册转换器和GenericConversionService
主线部分
- 实例化xmlApplicationContext
- 实例化XmlBeanDefinitionReader
- ResourceLoader定位bean文件
- XmlBeanDefinitionReader读入Resource
- DefaultBeanDefinitionDocumentReader解析Document
- 默认命名空间判断
- import元素判断
- alias元素判断
- beans元素递归
- 读取多个jar包中的META-INF/spring.handlers
- DefaultNamespaceResolver解析spring.handlers 文件,取得元素命名空间对应的NamespaceHandler
- NamespaceHandler解析Element元素
- 根据不同的Handler会生成或ComponentDefinition或BeanDefinition
- 注册BeanDefinition
import元素处理部分
- 重复主线中的3,4,5步
- 注册标志和别名
- 通过BeanfinitionParserDelegate解析bean元素
- 注册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>
发表评论
-
支持占位符的文本解析PropertySourcesPropertyResolver
2013-07-14 18:27 3000PropertyResolver 是 Environment的 ... -
支持不同运行环境下的属性处理--Environment 特性
2013-07-14 01:47 4123介绍 Environment架构是spring 3.1版本引 ... -
支持开发、测试、生产环境下bean配置切换的profiles特性
2013-07-11 12:31 5633介绍 Bean definition profiles ... -
方法缓存
2013-07-10 18:20 4245介绍 spring3.1之后提供了方法的缓存支持,透明的将 ... -
基于xml schema的扩展标签
2013-07-09 13:34 1571xml schema是spring 2.0版本之后引入的,在之 ... -
bean的创建周期回调
2013-06-29 16:24 1558初始化回调 实现org.springframework ... -
Scope实现原理
2013-06-27 18:02 3449内置Scope分类 Singleton 每个IOC容器对一个b ... -
MethodInjection 动态方法替换原理
2013-06-21 14:45 1435singleton实例依赖于prototy ... -
AbstractBeanFactory获取bean周期
2013-05-11 22:58 935AbstractBeanFactory是IOC容器实现的骨 ...
相关推荐
- **类型安全的 XML 解析**:XmlBean 将 XML 文档映射为 Java 类,允许开发者以面向对象的方式处理 XML 数据,避免了字符串操作的错误。 - **XML Schema 支持**:XmlBean 基于 XML Schema 来生成 Java 类,这使得 ...
BeanDefinition则是bean的元数据,存储了关于bean如何被创建和初始化的所有信息。 Spring源码中广泛应用了设计模式,如工厂模式(BeanFactory)、单例模式(Singleton)、代理模式(AOP代理)、装饰器模式...
1. Spring的核心组件:包括BeanFactory、ApplicationContext、BeanDefinition等。 2. Spring的依赖注入机制:包括依赖注入的原理、实现机制和应用场景。 3. Spring的AOP机制:包括AOP的原理、实现机制和应用场景。 4...
3. **BeanDefinition**:这是描述一个Bean的元数据,包括Bean的类、构造函数参数、属性值、作用域等。BeanDefinition在Spring配置文件或注解中定义,是Spring容器创建Bean的基础。 三、依赖注入与Bean的配置 依赖...
1. `BeanDefinition`:每个 Bean 在容器中都有一个对应的 `BeanDefinition`,它存储了 Bean 的所有元数据,如类名、初始化方法、依赖等。 2. `BeanFactory`:这是最基础的 Bean 容器接口,负责创建和管理 Bean。 3. ...
2. **spring-beans**:这个模块定义了Spring IoC容器的基本元素,包括BeanDefinition和FactoryBean。BeanDefinition存储了关于Bean的所有元信息,如类名、属性、依赖等。FactoryBean用于创建特殊的Bean,它可以返回...
Bean Definition Profiles 允许开发者根据不同的环境配置不同的Bean属性,这对于多环境的应用程序来说是非常有用的。 ##### 3. Environment Abstraction 环境抽象提供了一种机制,让开发者能够在不同的环境中使用...
- **配置文件(如applicationContext.xml)**:配置Spring容器,声明Activiti的bean,如流程引擎、数据源、事务管理器等。 - **测试类**:演示如何使用代码来操作流程,比如启动流程实例,查询当前用户的任务,完成...
Spring框架的主要组件包括BeanFactory、ApplicationContext、BeanDefinition等。 最后,SSH框架的持久层是指使用Hibernate框架来实现数据持久化。Hibernate框架是一个 ORM(Object-Relational Mapping)工具,它...
Spring资源抽象层是一个灵活的接口,可以读取来自不同源的数据流。Spring提供多种资源实现,包括文件系统资源、classpath资源和URL资源等。 **验证、数据绑定和类型转换** Spring提供了一套验证框架,允许开发者...
Spring的`BeanDefinition`接口是连接XML配置和实际对象的关键,它代表了一个bean的完整定义,包括其类、属性值、依赖关系等。`DefaultListableBeanFactory`使用`XmlBeanDefinitionReader`从XML文件加载bean定义,...
例如,Spring框架中的`org.springframework.beans.FatalBeanException`类在初始化Bean时会遍历BeanDefinition的属性,这里就使用了迭代器。另外,Apache Commons Collections库提供了丰富的迭代器实现,帮助开发者...
1. 流程定义(Process Definition):流程定义是Activiti的核心,它用BPMN 2.0标准的XML格式描述了一个业务流程。BPMN提供了丰富的图形符号,如开始事件、结束事件、用户任务、服务任务等,帮助开发者直观地设计流程...
接口的设计和实现取决于具体工作流产品,可能包括对Java Bean、Web服务、XML Bean和Spring Bean的调用。 3. **任务管理工具**:管理流程中的任务分配,为用户提供待办事项列表,确保任务的正确执行。这些工具通常...
- **Groovy Bean Definition DSL(Groovy Bean Definition DSL)**:引入了使用Groovy语言定义Bean的新方式。 - **核心容器改进(Core Container Improvements)**:增强了核心容器的功能。 - **通用Web改进(General Web...
Groovy Bean Definition DSL是一种使用Groovy语言定义Spring Bean的新方法,使得配置更加简洁和灵活。 **3.6 核心容器改进** 对Spring的核心容器进行了优化,提高了性能并增强了功能性。 **3.7 Web改进** 对Web...
它还包含BeanDefinition,用于存储Bean的元数据,以及BeanFactory和AbstractApplicationContext,是Spring IoC容器的基础。 4. **spring-web-4.0.0.RELEASE.jar**:该模块是Spring框架的Web支持部分,提供了与...
2. `org.springframework.beans-3.0.6.RELEASE.jar`: 这个模块包含用于处理Java Bean的工具类和接口,如BeanDefinition和BeanWrapper,它们是Spring管理bean的基础,支持属性注入、类型转换和bean的生命周期管理。...
- **Groovy Bean Definition DSL**:提供了 Groovy 语言编写配置文件的支持。 - **核心容器改进**:增强了 Bean 的生命周期管理,引入了新的 API。 - **Web 改进**:增强了 MVC 和 WebSocket 的支持。 - **...