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…