小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
Spring 内部,有很多地方可能需要将 String 转换为其他类型,今天我们一起来学习一下 PropertyEditor、
ConversionService、TypeConverter 三种类型转换的使用。
PropertyEditor
PropertyEditor 是 JDK 提供的类型转换器,首先创建 bean :
@Service
public class OrderItemService {
@Value("orderVal")
private Order order;
public void test() {
System.out.println("test order : " + order);
}
}
复制代码
创建类型转换器,将字符串转换为 Order 实例对象。
public class String2ObjectPropertyEditor extends PropertyEditorSupport implements PropertyEditor {
@Override
public void setAsText(String text) throws IllegalArgumentException {
Order order = new Order();
order.setName("haha");
order.setAge(12);
this.setValue(order);
}
}
复制代码
注册转换器以及测试代码:
@Import({OrderItemService.class})
@Configuration
public class PropertyEditorTest {
@Bean
public CustomEditorConfigurer customEditorConfigurer() {
Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>();
customEditors.put(Order.class, String2ObjectPropertyEditor.class);
CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();
customEditorConfigurer.setCustomEditors(customEditors);
return customEditorConfigurer;
}
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(PropertyEditorTest.class);
OrderItemService orderItemService = applicationContext.getBean(OrderItemService.class);
orderItemService.test();
}
}
复制代码
ConversionService
ConversionService 是 Sprign 中提供的类型转换器,它比 PrppertyEditor 功能更加强大。 定义转换器:
public class String2ObjectConversionService implements ConditionalGenericConverter {
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
return
Objects.equals(sourceType.getType(), String.class)
&&
Objects.equals(targetType.getType(), Order.class);
}
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(String.class, Order.class));
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
return new Order("haha", 32);
}
}
复制代码
在 Spring 中使用:
@Bean
public ConversionServiceFactoryBean conversionService() {
ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
conversionServiceFactoryBean.setConverters(Collections.singleton(new String2ObjectConversionService()));
return conversionServiceFactoryBean;
}
复制代码
Bean 的注入和调用代码:
// 测试和注入
@Service
public class OrderItemService {
//通过 @Value 注入
@Value("orderVal")
private Order order;
public void test() {
System.out.println("test order : " + order);
}
}
// 调用代码
ApplicationContext appliciton = new AnnotationConfigApplicationContext(ConvertTest.class);
OrderItemService orderItemService = appliciton.getBean(OrderItemService.class);
orderItemService.test();
复制代码
TypeConverter
TypeConverter 整合了 PropertyEditor 和 ConversionService, 在 Spring 内部使用:
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.registerCustomEditor(Order.class, new String2ObjectPropertyEditor());
Order order = typeConverter.convertIfNecessary("orderVal", Order.class);
System.out.println(order);
复制代码
比如在 AbstractBeanFacotry#adaptBeanInstance
中也有用到:
// AbstractBeanFacotry.java
<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
// Check if required type matches the type of the actual bean instance.
// 如果转换类型不为空,并且 bean 类型与目标类型不匹配
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
// 尝试转换
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
复制代码
近期评论