spring 之 类型转换 2
spring内置的转换器
在spring xml 文件中,配置属性的时候, 不管实际是 list 还是map ,还是Date, 或者原生的java 类型, 我们只能配置xml 给它们。 那么 spring 在实例化bean 的时候, 这些属性是必须要经过转换的。 那么,spring 具体是怎么实现的呢?
答案就是:
public class DefaultConversionService extends GenericConversionService {
private static final boolean javaUtilOptionalClassAvailable = ClassUtils.isPresent("java.util.Optional", DefaultConversionService.class.getClassLoader());
private static final boolean jsr310Available = ClassUtils.isPresent("java.time.ZoneId", DefaultConversionService.class.getClassLoader());
private static final boolean streamAvailable = ClassUtils.isPresent("java.util.stream.Stream", DefaultConversionService.class.getClassLoader());
private static volatile DefaultConversionService sharedInstance;
public static ConversionService getSharedInstance() {
if(sharedInstance == null) {
Class var0 = DefaultConversionService.class;
synchronized(DefaultConversionService.class) {
if(sharedInstance == null) {
sharedInstance = new DefaultConversionService();
}
}
}
return sharedInstance;
}
public DefaultConversionService() {
addDefaultConverters(this);
}
public static void addDefaultConverters(ConverterRegistry converterRegistry) {
addScalarConverters(converterRegistry); // 注册 标量的转换器, 也就是把xml配置文件中 字面值 转换为 常见的简单的普通类型
addCollectionConverters(converterRegistry); // 转换为 集合
converterRegistry.addConverter(new ByteBufferConverter((ConversionService)converterRegistry));
if(jsr310Available) {
DefaultConversionService.Jsr310ConverterRegistrar.registerJsr310Converters(converterRegistry);
}
converterRegistry.addConverter(new ObjectToObjectConverter());
converterRegistry.addConverter(new IdToEntityConverter((ConversionService)converterRegistry));
converterRegistry.addConverter(new FallbackObjectToStringConverter());
if(javaUtilOptionalClassAvailable) {
converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService)converterRegistry));
}
}
public static void addCollectionConverters(ConverterRegistry converterRegistry) {
ConversionService conversionService = (ConversionService)converterRegistry;
converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));
converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
converterRegistry.addConverter(new MapToMapConverter(conversionService));
converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
converterRegistry.addConverter(new StringToArrayConverter(conversionService));
converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));
converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
converterRegistry.addConverter(new StringToCollectionConverter(conversionService));
converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));
if(streamAvailable) {
converterRegistry.addConverter(new StreamConverter(conversionService));
}
}
private static void addScalarConverters(ConverterRegistry converterRegistry) {
converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());
converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToCharacterConverter());
converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new NumberToCharacterConverter());
converterRegistry.addConverterFactory(new CharacterToNumberFactory());
converterRegistry.addConverter(new StringToBooleanConverter());
converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
converterRegistry.addConverter(new EnumToStringConverter((ConversionService)converterRegistry));
converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());
converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService)converterRegistry));
converterRegistry.addConverter(new StringToLocaleConverter());
converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToCharsetConverter());
converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToCurrencyConverter());
converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());
converterRegistry.addConverter(new StringToPropertiesConverter());
converterRegistry.addConverter(new PropertiesToStringConverter());
converterRegistry.addConverter(new StringToUUIDConverter());
converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
}
private static final class Jsr310ConverterRegistrar {
private Jsr310ConverterRegistrar() {
}
public static void registerJsr310Converters(ConverterRegistry converterRegistry) {
converterRegistry.addConverter(new StringToTimeZoneConverter());
converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());
}
}
}
大致的堆栈是:
at org.springframework.core.convert.support.StringToNumberConverterFactory$StringToNumber.convert(StringToNumberConverterFactory.java:59)
at org.springframework.core.convert.support.StringToNumberConverterFactory$StringToNumber.convert(StringToNumberConverterFactory.java:49)
at org.springframework.core.convert.support.GenericConversionService$ConverterFactoryAdapter.convert(GenericConversionService.java:436)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:37)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:203)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:173)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:576)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:603)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:216)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1538)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1497)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1237)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:552)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
- locked <0x677> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
spring xml中常见属性的注入:
注入array 或者list 有两种方式:
1 直接使用 <value>, 每个 item 使用 逗号分隔, 这个时候使用的是 StringToCollectionConverter
如:
<property name="strArr">
<value>aaa,bbb,ccc</value>
</property>
2 使用 <list> 子标签, (别看名字是 list, 但它可以转换list 和 array; spring 并没有单独对 数组即 array 进行转换, 而是把list/array 统一为 list 了) 。但是实际处理的时候是区分开了的, array 使用的是 ArrayToArrayConverter, list 使用的是CollectionToCollectionConverter 。
<property name="strArr">
<list>
<value> // list 下面每个 value 是一个item
AAA
</value>
<value>
BBB
</value>
<value>
CCC
</value>
</list> </property>
注入Set 有两种方式:
同样, 注入set 也有两种方式:
1 使用 <value> , 和数组或list相同, 这个时候使用的是 StringToCollectionConverter,
2 或者使用 <set> 标签 ,对应 set 使用的和数组和list相同: CollectionToCollectionConverter ;
<property name="aSet">
<set><value>aaa</value><value>bbb</value></set>
</property>
注入Map 或者 Properties:
而, 对于map 或者 properties 的注入, 可以使用<map> 或者 <props> ( 因为他们是可以相互转换的). 对应的 都 是MapToMapConverter
<property name="strMap">
<props>
<prop key="k1">V1</prop>
<prop key="k2">V2</prop>
</props>
</property>
<property name="strProp">
<map>
<entry key="aa" value="AA"></entry>
<entry key="bb" value="BB"></entry>
</map>
</property>
另外, 对于 properties, 我们还可以使用 value 直接注入, 它实际使用的转换器是:StringToPropertiesConverter
格式是, 每行一个 entry, 用 = 分隔 kv :
<property name="strProp">
<value>
aa = aa
bb = BB
</value>
</property> 但是map 不能这样注入。 因为并不存在 StringToMapConverter
spring 之 类型转换 2的更多相关文章
- Spring ConversionService 类型转换(一)Converter
Spring ConversionService 类型转换(一)Converter Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.h ...
- Spring ConversionService 类型转换(二) ConversionService
Spring ConversionService 类型转换(二) ConversionService Spring 系列目录(https://www.cnblogs.com/binarylei/p/1 ...
- spring 之 类型转换
在spring中, 提供了至少三种的 类型转换方式: ConversionServiceFactoryBean, FormattingConversionServiceFactoryBean, C ...
- spring自动类型转换========Converter和PropertyEditor
Spring有两种自动类型转换器,一种是Converter,一种是propertyEditor. 两者的区别:Converter是类型转换成类型,Editor:从string类型转换为其他类型. 从某 ...
- 2. Spring早期类型转换,基于PropertyEditor实现
青年时种下什么,老年时就收获什么.关注公众号[BAT的乌托邦],有Spring技术栈.MyBatis.JVM.中间件等小而美的原创专栏供以免费学习.分享.成长,拒绝浅尝辄止.本文已被 https:// ...
- Spring MVC类型转换
类型转换器引入 为什么页面上输入"12",可以赋值给Handler方法对应的参数?这是因为框架内部帮我们做了类型转换的工作.将String转换成int 但默认类型转换器并不是可以将 ...
- Spring MVC 类型转换
SpringMVC类型转换: 1 日期类型转换: private Date birthday; <label for="">生日:<input type=&quo ...
- Spring类型转换(Converter)
Spring的类型转换 以前在面试中就有被问到关于spring数据绑定方面的问题,当时对它一直只是朦朦胧胧的概念,最近稍微闲下来有时间看了一下其中数据转换相关的内容,把相应的内容做个记录. 下面先说明 ...
- Spring官网阅读(十四)Spring中的BeanWrapper及类型转换
文章目录 接口定义 继承关系 接口功能 1.PropertyEditorRegistry(属性编辑器注册器) 接口定义 PropertyEditor 概念 Spring中对PropertyEditor ...
随机推荐
- inode 与black 特点与简介
inodo为索引节点, 存放文件属性的信息(实际文件位置与容量信息 /black文件属性) 作用在格式化文件系统时候产生 创建一个文件就占用一个inode 数字相同为硬链接 black为实际数据/内容 ...
- L1-057 PTA使我精神焕发
以上是湖北经济学院同学的大作.本题就请你用汉语拼音输出这句话. 输入格式: 本题没有输入. 输出格式: 在一行中按照样例输出,以惊叹号结尾. 输入样例: 无 输出样例: PTA shi3 wo3 ji ...
- 20175224 2018-2019-2 《Java程序设计》第二周学习总结
教材学习内容总结 本周对教材的第二第三章进行了学习,通过阅读教材,我发现java和c语言在相似的基础上还是有很多不同的地方,以下是我对这周学习知识的一些总结. 2.1 java标识符中的字母是区分大小 ...
- setTimeout中调用this
项目案例: 左右切换tab容器的动作,封装到一个对象中: var slidingComp = { startX : 0 , moveX : 0 , ...... start : function(e) ...
- 计时 timeit
python中的计时器:timeit timeit 通常在一段程序的前后都用上time.time(),然后进行相减就可以得到一段程序的运行时间,不过python提供了更强大的计时库:timeit #导 ...
- poi读取word的内容
pache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 1.读取word 2003及word 2007需要的 ...
- Python 事件
from multiprocessing import Process,Event e = Event() #创建事件对象,这个对象的初识状态为False print('e的状态是:',e.is_se ...
- net start/stop mysql access denied.拒绝访问
转载:Mysql net start mysql启动,提示发生系统错误 5 拒绝访问 解决之道 为什么会出现这个问题呢?经过一番思考找到原因了,是因为当前用户的操作权限太低了,出了问题 出错问题截屏如 ...
- spring ico
代码非常简单.如果缺少jar包将导致报错. 需要5个spring jar包和1个logging jar,否则报错. org.springframework.asm.jarorg.springframe ...
- 文笔很差系列1 - 也谈谈AlphaGo
距离AlphaGo击败李世石已经过去数月了,心中的震撼至今犹在,全刊报道此项比赛的<围棋天地>杂志我已经看了不下十遍.总也想说点自己的意见,却也不知道从哪里说起,更不知道想表达些什么. 作 ...