- 浏览: 92338 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
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 2939PropertyResolver 是 Environment的 ... -
支持不同运行环境下的属性处理--Environment 特性
2013-07-14 01:47 4087介绍 Environment架构是spring 3.1版本引 ... -
支持开发、测试、生产环境下bean配置切换的profiles特性
2013-07-11 12:31 5541介绍 Bean definition profiles ... -
方法缓存
2013-07-10 18:20 4191介绍 spring3.1之后提供了方法的缓存支持,透明的将 ... -
基于xml schema的扩展标签
2013-07-09 13:34 1542xml schema是spring 2.0版本之后引入的,在之 ... -
bean的创建周期回调
2013-06-29 16:24 1527初始化回调 实现org.springframework ... -
Scope实现原理
2013-06-27 18:02 3316内置Scope分类 Singleton 每个IOC容器对一个b ... -
MethodInjection 动态方法替换原理
2013-06-21 14:45 1398singleton实例依赖于prototy ... -
AbstractBeanFactory获取bean周期
2013-05-11 22:58 897AbstractBeanFactory是IOC容器实现的骨 ...
相关推荐
Spring BeanDefinition 类图结构,形象展示Spring是如何存储Bean信息的。通过类图和源码更好的理解Spring BeanDefinition存储结构
在本文中,我将讨论棘手的Spring Boot bean定义覆盖机制。 为了使您对该主题更加清楚,让我们从小测验开始。请看下一个简单的例子。 因此,我们有2种配置,它们使用名称beanName实例化bean,在主应用程序中,我们仅...
Spring Bean Factory, Bean definition 结构图;processOn
今天小编就为大家分享一篇关于BeanDefinition基础信息讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
Spring源码学习五:BeanDefinition装载1
* Role hint indicating that a {@code BeanDefinition} is a supporting* part of so
为什么要读Spring源码,...看几篇博客,对照着看看源码,应该就没什么问题了,但是如果想真正的玩懂Spring,需要花的时间真的很多,需要你沉下心,从最基础的看起,今天我们就来看看Spring中的基础——BeanDefinition。
撸一撸Spring Framework-IoC-BeanDefinition(csdn)————程序
Bean保存成流文件,读取文件转换成bean
框架的源码分析,有些代码可以暂时忽略,如Spring如何进行XML模式校验的、XML解析的细节等,这些代码可以在了解了整体的原理之后,再做针对性的分析,关注重点
(2)然后筛选出非懒加载的单例Bean Definition 对象进行创建Bean,多实例的Bean会在每次获取Bean时利用Bean Definition去创建 (3)利用Bean definition创建Bean就是Bean的创建生命周期,包括:合并Bean Definition ...
逻辑回归、感知机、深度神经网络、支持向量机等模型训练数据。
第四章:Spring Bean 基础小马哥 · mercyblitzSpring Bean 基础定义 Spring BeanBeanDefinition 元信息
本文深入探讨了Spring的核心API,包括BeanFactory、BeanDefinition以及事务管理等关键组件。 BeanFactory是Spring框架的心脏,作为Bean容器的根接口,它采用工厂模式来管理Bean的生命周期。BeanDefinition则详细描述...
1、<bean>标签主要用来进行Bean定义; 2、alias用于定义Bean别名的;...这两种方式都是通过调用Bean Definition Reader 读取Bean定义,内部实现没有任何区别。标签可以放在下的任何位置,没有顺序关系。
小弹簧第一部分:IoC容器1.step1-最...注入beanBeanDefinition beanDefinition = new BeanDefinition ( new HelloWorldService ());beanFactory . registerBeanDefinition( " helloWorldService " , beanDefinition);//
4. 搞清楚注册BeanDefinition流程中各个类的作用 5. 搞清楚创建Bean实例流程中各个类的作用 6. 通过以上接口和类的理解,我们写出IoC模块的V3版本 7. 可以自主完成阅读Spring框架中BeanDefinition注册流程的源码 8. ...
Dataset Information Additional Information Seven different types of dry beans were used in this research, taking into account the features such as form, shape, type, and structure by the market ...
如果你要反向生成数据库表,那么来下载试试吧!祝你好运