弹簧双向转换器

Spring 3具有类型转换这样一个很好的function。 它提供了一个转换器SPI( Converter ),用于实现差分转换逻辑。 Converter类型的子类允许定义单向转换(仅从S到T),因此如果我还希望从T到SI执行Converter需要定义另一个实现Converter转换器类。 如果我有许多可以转换的类,我需要定义许多转换器。 是否有可能在一个转换器中定义双向转换逻辑(从S到T和从T到S)? 以及它将如何使用?

PS。 现在我通过ConversionServiceFactoryBean使用我的转换器在配置文件中定义/注入它们

你是对的,如果你想直接使用org.springframework.core.convert.converter.Converter接口,你需要实现两个转换器,每个方向一个。

但是spring3还有其他两个选择:

  1. 如果您的转换不是对象到对象,而是对象到字符串(和返回),那么您可以实现org.springframework.format.Formatter 。 格式化程序注册为GenericConverters(请参阅http://static.springsource.org/spring-webflow/docs/2.3.x/reference/html/ch05s07.html#converter-upgrade-to-spring-3 )

  2. 否则,您可以实现自己的org.springframework.core.convert.converter.GenericConverter ,这样可以轻松地使用reflection创建TwoWayConverter实现。

     public abstract class AbstractTwoWayConverter implements GenericConverter { private Class classOfS; private Class classOfT; protected AbstractTwoWayConverter() { Type typeA = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; Type typeB = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]; this.classOfS = (Class) typeA; this.classOfT = (Class) typeB; } public Set getConvertibleTypes() { Set convertiblePairs = new HashSet(); convertiblePairs.add(new ConvertiblePair(classOfS, classOfT)); convertiblePairs.add(new ConvertiblePair(classOfT, classOfS)); return convertiblePairs; } public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (classOfS.equals(sourceType.getType())) { return this.convert((S) source); } else { return this.convertBack((T) source); } } protected abstract T convert(S source); protected abstract S convertBack(T target); } /** * converter to convert between a userId and user. * this class can be registered like so: * conversionService.addConverter(new UserIdConverter (userDao)); */ public class UserIdConverter extends AbstractTwoWayConverter { private final UserDao userDao; @Autowired public UserIdConverter(UserDao userDao) { this.userDao = userDao; } @Override protected User convert(String userId) { return userDao.load(userId); } @Override protected String convertBack(User target) { return target.getUserId(); } } 

Spring就是这样一个接口:TwoWayConverter。 请参阅以下内容: http : //static.springsource.org/spring-webflow/docs/2.0.x/javadoc-api/org/springframework/binding/convert/converters/TwoWayConverter.html

您可以使用Spring Formatter将类型为T的对象格式化为String,反之亦然。

 package org.springframework.format; public interface Formatter extends Printer, Parser { } 

使用此接口可以实现与Barry Pitman所说的相同,但代码更少,如果您要格式化为String,这是Spring文档的首选方法,反之亦然。 所以Barry的UserIdConverter类看起来像这样:

 public class UserIdConverter implements Formatter { private final UserDao userDao; @Autowired public UserIdConverter(UserDao userDao) { this.userDao = userDao; } @Override public User parse(String userId, Locale locale) { return userDao.load(userId); } @Override public String print(User target, Locale locale) { return target.getUserId(); } } 

要注册此Formatter,您应该在XML配置中包含它:

 ...         ... 

! 请注意,此类只能用于从某种类型T到String的格式化,反之亦然。 例如,您无法将类型T格式化为其他类型T1。 如果您有这种情况,您应该使用Spring GenericConverter并使用Barry Pitman答案:

 public abstract class AbstractTwoWayConverter implements GenericConverter { private Class classOfS; private Class classOfT; protected AbstractTwoWayConverter() { Type typeA = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; Type typeB = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]; this.classOfS = (Class) typeA; this.classOfT = (Class) typeB; } public Set getConvertibleTypes() { Set convertiblePairs = new HashSet(); convertiblePairs.add(new ConvertiblePair(classOfS, classOfT)); convertiblePairs.add(new ConvertiblePair(classOfT, classOfS)); return convertiblePairs; } public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (classOfS.equals(sourceType.getType())) { return this.convert((S) source); } else { return this.convertBack((T) source); } } protected abstract T convert(S source); protected abstract S convertBack(T target); } /** * converter to convert between a userId and user. * this class can be registered like so: * conversionService.addConverter(new UserIdConverter (userDao)); */ public class UserIdConverter extends AbstractTwoWayConverter { private final UserDao userDao; @Autowired public UserIdConverter(UserDao userDao) { this.userDao = userDao; } @Override protected User convert(String userId) { return userDao.load(userId); } @Override protected String convertBack(User target) { return target.getUserId(); } } 

并添加到您的XML配置:

 ...         ...