我有一个用于映射java bean的接口
public interface Mapper <K,V> {
K map(V v);
V mapReverse(K k);
}
实施示例
public class CarMapper implements Mapper<Car, CarDTO> {
public Car map(CarDTO dto) {
//implementation
};
public CarDTO mapReverse(Car car) {
//implementation
};
}
现在我想为所有这些实现提供一个公共访问点,以便用户不必记住所有实现的名称。
例如: -
public class MapperFacade {
public static<K,V> K map(V v, Class<K> k, Class<V> v) {
//1) get the appropriate mapper implementation (throw an exception if no such implementation is found)
//2) map the object
//3) return the object
}
}
现在我有两个问题: -
1)如何在运行时获得适当的mapper实现并知道要调用哪个方法(map或mapReverse)。
2)如果Mapper实现分布在不同的java项目中,我如何创建一个框架,其中每个mapper实现可以在中心位置注册自己,然后可以通过上面提到的公共点访问
答案 0 :(得分:0)
我还没有测试过这个但是这样的事情怎么样。使用类作为键在映射中注册映射器。更完整的实现将使用isAssignable检查,而不仅仅是精确的类匹配。如果映射的值是基类的子类。
public class MapperFacade<K,V> implements Mapper<K,V> {
private Map<Class<K>,Mapper<K,V>> keyMappers = new HashMap<Class<K>,Mapper<K,V>>();
private Map<Class<V>,Mapper<K,V>> valueMappers = new HashMap<Class<V>,Mapper<K,V>>();
public void addMapper(Mapper<K,V> mapper, Class<K> keyClass, Class<V> valueClass) {
keyMappers.put(keyClass, mapper);
valueMappers.put(valueClass, mapper);
}
public K map(V value) {
Mapper<K,V> mapper = valueMappers.get(value.getClass());
return mapper.map(value);
}
public V mapReverse(K key) {
Mapper<K,V> mapper = keyMappers.get(key.getClass());
return mapper.mapReverse(key);
}
}
或制作地图方法&#34;不那么神奇&#34;通过提供类,如在代码中(MapperFacade不再实现Mapper)
public K map(V value, Class<V> valueClass) {
Mapper<K,V> mapper = valueMappers.get(valueClass);
return mapper.map(value);
}
public V mapReverse(K key, Class<V> keyClass) {
Mapper<K,V> mapper = keyMappers.get(keyClass);
return mapper.mapReverse(key);
}
这假定每个类有一个映射器。如果同一个类可能有多个映射器,则可能需要使用单个HashMap,而是使用由Class<K>
和Class<V>
组成的键的bean - 或者两个地图映射...
private Map<Class<K>,Map<Class<V>,Mapper<K,V>>> keyMappers = ...
private Map<Class<V>,Map<Class<K>,Mapper<K,V>>> valueMappers = ...
答案 1 :(得分:0)
你正在重新实现番石榴的BiMap。使用它。
答案 2 :(得分:0)
1)如何在运行时获得适当的映射器实现 知道调用哪个方法(map或mapReverse)。
要在运行时探索元级别信息,您可以尝试Reflectons。
之类的内容它允许您查询&#34;运行时的类定义元数据:
Reflections reflections = new Reflections("my.project");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
因此,用于查找Mapper
的正确实现的查找表可以是动态的。但请确保这种方法的优缺点。特别是你将如何维护课程。
2)如果Mapper实现分布在不同的java上 项目,我如何创建每个mapper实现的框架 可以在中心位置注册,然后可以通过访问 如上所述的共同点
如果最终程序是所有这些子项目的集成(即编译为一个),那么除了使用上述方法扫描类路径之外,没有什么特别需要做的。否则,如果这些子项目在不同的环境(远程)中运行,那么您必须探索more approaches.
答案 3 :(得分:0)
所以我最近用弹簧解决了这个问题。 这是解决方案
首先,将Mapper接口重构为: -
public abstract class Mapper <Entity, DTO> {
private static final MapperFactory mapperFactory = MapperFactory.getInstance();
public Mapper() {
mapperFactory.registerMapper(getEntityClass(), getDTOClass(),this);
}
public abstract Entity map(DTO object);
public abstract DTO mapReverse(Entity object);
public abstract Class<Entity> getEntityClass();
public abstract Class<DTO> getDTOClass();
}
public class MapperFactory {
private Map<String, Mapper> mappers = new ConcurrentHashMap<>(); //MapperFactory is a singleton class, ConcurrentHashMap ensures thread safety.
private static final MapperFactory INSTANCE = new MapperFactory();
public static MapperFactory() {
return MapperFactory.INSTANCE;
}
public <Entity, DTO> void registerMapper(Class<Entity> entityClass, Class<DTO> dtoClass, Mapper<Entity, DTO> mapper) {
mappers.put(dtoClass.getCanonicalName(), mapper);
mappers.put(entityClass.getCanonicalName(), mapper);
}
public <T> Mapper getMapper(Class<T> sourceClass) {
mappers.get(sourceClass.getCanonicalName());
}
}
对于访问所有映射器的通用接口,请使用以下类: -
public class MapperFacade {
private MapperFactory mapperFactory = MapperFactory.getInstance();
public <Entity, DTO> DTO entityToDTO(Entity entity, Class<DTO> dtoClass) {
Mapper<Entity, DTO> mapper = mapperFactory.getMapper(entity.getClass());
return mapper.mapReverse(entity);
}
public <Entity, DTO> Entity dtoToEntity(DTO dto, Class<Entity> entityClass) {
Mapper<Entity, DTO> mapper = mapperFactory.getMapper(dto.getClass());
return mapper.map(dto);
}
}
现在,对于自动注册任何映射器,我们可以使用spring的@Component注释。例如: -
@Component
public class CarMapper <Car, CarDTO> {
public Car map(CarDTO carDTO) {
//impl
}
public CarDTO mapReverse(Car car) {
//impl
}
public Class<Car> getEntityClass() {
return Car.getClass();
}
public Class<CarDTO> getDtoClass() {
return CarDTO.getClass();
}
}
所以现在你不必关心映射器类是什么,也不需要在一些初始化代码中自己注册它们。