Bypass conversion when possible

Prior to this commit conversion between like types would often result in
a copy of the object. This can be problematic in the case of large byte
arrays and objects that do not have a default constructor.

The ConversionService SPI now includes canBypassConvert methods that can
be used to deduce when conversion is not needed. Several existing
converters have been updated to ensure they only apply when source and
target types differ.

This change introduces new methods to the ConversionService that will
break existing implementations. However, it anticipated that most users
are consuming the ConversionService interface rather then extending it.

Issue: SPR-9566
This commit is contained in:
Phillip Webb
2012-10-26 17:43:41 -07:00
committed by Chris Beams
parent f13e3ad72b
commit a27d1a28ff
6 changed files with 93 additions and 9 deletions
@@ -19,6 +19,7 @@ package org.springframework.core.convert.support;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -709,6 +710,30 @@ public class GenericConversionServiceTests {
assertEquals(Object.class, last.getType());
}
@Test
public void convertOptimizeArray() throws Exception {
// SPR-9566
GenericConversionService conversionService = new DefaultConversionService();
byte[] byteArray = new byte[] { 1, 2, 3 };
byte[] converted = conversionService.convert(byteArray, byte[].class);
assertSame(byteArray, converted);
}
@Test
public void convertCannotOptimizeArray() throws Exception {
GenericConversionService conversionService = new GenericConversionService();
conversionService.addConverter(new Converter<Byte, Byte>() {
public Byte convert(Byte source) {
return (byte) (source + 1);
}
});
DefaultConversionService.addDefaultConverters(conversionService);
byte[] byteArray = new byte[] { 1, 2, 3 };
byte[] converted = conversionService.convert(byteArray, byte[].class);
assertNotSame(byteArray, converted);
assertTrue(Arrays.equals(new byte[] { 2, 3, 4 }, converted));
}
private static class MyConditionalConverter implements Converter<String, Color>,
ConditionalConversion {