Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
Inside Spring, there are many places where you might want to convert a String to another type. Today we’ll look at the use of PropertyEditor, ConversionService, and TypeConverter.
PropertyEditor
PropertyEditor is a type converter provided by the JDK that first creates a bean:
@Service
public class OrderItemService {
@Value("orderVal")
private Order order;
public void test(a) {
System.out.println("The test order."+ order); }}Copy the code
Create a type converter to convert a string to an Order instance object.
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); }}Copy the code
Register converter and test code:
@Import({OrderItemService.class})
@Configuration
public class PropertyEditorTest {
@Bean
public CustomEditorConfigurer customEditorConfigurer(a) { 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 = newAnnotationConfigApplicationContext(PropertyEditorTest.class); OrderItemService orderItemService = applicationContext.getBean(OrderItemService.class); orderItemService.test(); }}Copy the code
ConversionService
ConversionService is a type converter provided in Sprign that is more powerful than PrppertyEditor. Define converter:
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(a) {
return Collections.singleton(new ConvertiblePair(String.class, Order.class));
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
return new Order("haha".32); }}Copy the code
Use in Spring:
@Bean
public ConversionServiceFactoryBean conversionService(a) {
ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();
conversionServiceFactoryBean.setConverters(Collections.singleton(new String2ObjectConversionService()));
return conversionServiceFactoryBean;
}
Copy the code
The Bean injection and invocation code:
// Test and inject
@Service
public class OrderItemService {
// Inject via @value
@Value("orderVal")
private Order order;
public void test(a) {
System.out.println("The test order."+ order); }}// Call code
ApplicationContext appliciton = new AnnotationConfigApplicationContext(ConvertTest.class);
OrderItemService orderItemService = appliciton.getBean(OrderItemService.class);
orderItemService.test();
Copy the code
TypeConverter
TypeConverter incorporates PropertyEditor and ConversionService to be used within Spring:
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
typeConverter.registerCustomEditor(Order.class, new String2ObjectPropertyEditor());
Order order = typeConverter.convertIfNecessary("orderVal", Order.class);
System.out.println(order);
Copy the code
For example, AbstractBeanFacotry#adaptBeanInstance also works:
// AbstractBeanFacotry.java
<T> T adaptBeanInstance(String name, Object bean, @NullableClass<? > requiredType) {
// Check if required type matches the type of the actual bean instance.
// If the conversion type is not empty and the bean type does not match the target type
if(requiredType ! =null && !requiredType.isInstance(bean)) {
try {
// Try conversion
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 newBeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); }}return (T) bean;
}
Copy the code
The resources
- Docs. Spring. IO/spring – fram…