我正在尝试为我的dto <->实体类创建一个通用的对象转换器。我创建了一个抽象类,它具有两个表示两种转换的函数,然后将其扩展到我的具体转换器类中。
但是我想拥有一个通用的转换服务,我可以在启动期间注册所有转换器,然后方便地调用一个方法来处理彼此之间的转换。
这是我到目前为止提出的:
转换器抽象类
public abstract class Converter<D, E> {
private final Function<D, E> fromFirstToSecond;
private final Function<E, D> fromSecondToFirst;
public Converter(final Function<D, E> fromFirstToSecond, final Function<E, D> fromSecondToFirst) {
this.fromFirstToSecond = fromFirstToSecond;
this.fromSecondToFirst = fromSecondToFirst;
}
public final E convertFromFirstToSecond(final D first) {
return fromFirstToSecond.apply(first);
}
public final D convertFromSecondToFirst(final E second) {
return fromSecondToFirst.apply(second);
}
}
转换器具体类
public class MyConverter extends Converter<MyDTO, MyEntity> {
public OrderConverter() {
super(
MyConverter::fromDTOToEntity,
MyConverter::fromEntityToDTO
);
}
private static MyEntity fromDTOToEntity(MyDTO dto) {
return MyEntity.builder()
.field1(dto.getField1())
.field2(dto.getField2())
.build();
}
private static MyDTO fromEntityToDTO(MyEntity entity) {
return MyDTO.builder()
.field1(entity.getField1())
.field2(entity.getField2())
.build();
}
}
我想实现这样的目标(这是我需要帮助的地方):
@Configuration
public class ConverterConfiguration {
@Bean
public ConverterService converterService() {
ConverterService converterService = new ConverterService();
converterService.registerConverter(new MyConverter());
// Register any other converter...
return converterService;
}
}
服务看起来像这样:
public class ConverterService {
private Map<Key, Converter<?, ?>> converters = new ConcurrentReferenceHashMap<>();
public void registerConverter(Converter<?, ?> converter) {
this.converterCache.put(key, converter);
}
protected <I, O> I mapBetweenTypes(final O from, final Class<I> clazz) {
// Based on the parameters I should be able to figure out which function to get from the map and then call (convertFromFirstToSecond or convertFromSecondToFirst)
// return this.converters.get(key).convertFromFirstToSecond(from);
return this.converters.get(key).convertFromSecondToFirst(from);
}
}
答案 0 :(得分:1)
解决该问题的一种方法是在Converter
类中显式存储属于转换的类型。我考虑的另一个简化方法是将转换函数直接存储在映射中,而不是使用转换器。然后,您不必弄清楚该走哪条路。
第一步,存储类型,并为转换函数添加getter:
public abstract class Converter<D, E> {
private final Function<D, E> fromFirstToSecond;
private final Function<E, D> fromSecondToFirst;
private final Class<D> classOfFirst;
private final Class<E> classOfSecond;
public Class<D> getClassOfFirst() {
return classOfFirst;
}
public Class<E> getClassOfSecond() {
return classOfSecond;
}
public Converter(Class<D> first, Class<E> second,
Function<D, E> fromFirstToSecond, Function<E, D> fromSecondToFirst) {
this.fromFirstToSecond = fromFirstToSecond;
this.fromSecondToFirst = fromSecondToFirst;
classOfFirst = first;
classOfSecond = second;
}
public Function<D, E> getForward() {
return fromFirstToSecond;
}
public Function<E, D> getBackward() {
return fromSecondToFirst;
}
然后ConverterService
可以在两个方向上存储转换函数,并且转换等于在两级映射中进行查找。
public class ConverterService {
private Map<Class<?>, Map<Class<?>, Function<?,?>>> converters = createMap();
public void registerConverter(Converter<?, ?> converter) {
if( !converters.containsKey(converter.getClassOfFirst())) {
converters.put(converter.getClassOfFirst(), createInnerMap());
}
if( !converters.containsKey(converter.getClassOfSecond())) {
converters.put(converter.getClassOfSecond(), createInnerMap());
}
converters.get(converter.getClassOfFirst()).put(
converter.getClassOfSecond(), converter.getForward());
converters.get(converter.getClassOfSecond()).put(
converter.getClassOfFirst(), converter.getBackward());
}
@SuppressWarnings("unchecked") // Also needs input validation
protected <D,E> E mapBetweenTypes(D from, E to) {
return ((Function<D,E>) converters.get(
from.getClass()).get(to.getClass())).apply(from);
}
private static Map<Class<?>, Map<Class<?>, Function<?,?>>> createMap() {
return /* Whatever impl you need */
}
private static Map<Class<?>, Function<?,?>> createInnerMap() {
return /* Whatever impl you need */
}
}