[英]Hazelcast Adding Index for Map with Objects of different classes implementing same interface
[英]How to register objects of classes implementing the same interface
我有一個這樣的映射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實現都可以在一個中央位置注冊自己,然后可以通過一個公共點進行訪問,如上所述
我還沒有測試過,但是這樣的事情怎么樣。 使用類作為鍵在地圖中注冊映射器。 一個更完整的實現將使用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);
}
}
或通過提供類,使映射方法“減少魔力”,如您的代碼中一樣(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-或兩個Maps…
private Map<Class<K>,Map<Class<V>,Mapper<K,V>>> keyMappers = ...
private Map<Class<V>,Map<Class<K>,Mapper<K,V>>> valueMappers = ...
您正在重新實現Guava的BiMap 。 用那個
1)如何在運行時獲取適當的mapper實現,並知道要調用的方法(map或mapReverse)。
要在運行時瀏覽元級別的信息,可以嘗試使用Reflectons之類的東西。
它允許您在運行時“查詢”類定義元數據:
Reflections reflections = new Reflections("my.project");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
因此,用於查找正確的Mapper
實現的查找表可以是動態的。 但是請確定這種方法的優缺點。 特別是您將如何維護課程。
2)如果Mapper實現分散在不同的Java項目中,我該如何創建一個框架,使每個Mapper實現都可以在一個中央位置注冊自己,然后可以通過一個公共點進行訪問,如上所述
如果最終程序是所有這些子項目的集成(即編譯為一個),則除了使用上述方法掃描類路徑之外,無需執行任何特殊操作。 否則,如果這些子項目在單獨的環境中運行(遠程),則您必須探索更多方法。
所以最近我自己用spring解決了這個問題。 這是解決方案
首先,將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();
}
}
因此,現在您不必關心映射器類是什么,也不需要自己在一些初始化代碼中注冊它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.