Java 如何注册实现同一接口的类的对象

Java 如何注册实现同一接口的类的对象,java,interface,Java,Interface,我有这样一个映射JavaBean的接口 public interface Mapper <K,V> { K map(V v); V mapReverse(K k); } 公共接口映射器{ K图(V); V图反向(K); } 实现示例 public class CarMapper implements Mapper<Car, CarDTO> { public Car map(CarDTO dto) { //implementat

我有这样一个映射JavaBean的接口

public interface Mapper <K,V> {
    K map(V v);
    V mapReverse(K k);
}
公共接口映射器{
K图(V);
V图反向(K);
}
实现示例

public class CarMapper implements Mapper<Car, CarDTO> {
    public Car map(CarDTO dto) {
         //implementation
    };

    public CarDTO mapReverse(Car car) {
         //implementation
    };
}
公共类CarMapper实现映射器{
公共汽车地图(CarDTO dto){
//实施
};
公共卡至地图倒车(汽车){
//实施
};
}
现在我想为所有这些实现提供一个公共访问点,这样用户就不必记住所有实现的名称

例如:-

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
    }
}
公共类MapperFacade{
公共静态K图(V,K类,V类){
//1) 获取适当的映射器实现(如果未找到此类实现,则引发异常)
//2) 映射对象
//3) 返回对象
}
}
现在我有两个问题:-

1) 如何在运行时获得适当的映射器实现,并知道调用哪个方法(map或mapReverse)


2) 如果映射器实现分布在不同的java项目中,我如何创建一个框架,其中每个映射器实现可以在一个中心位置注册自己,然后可以通过一个公共点进行访问,如上文所述

我没有测试过这一点,但类似的情况如何。使用类作为键在地图中注册映射器。更完整的实现将使用可分配检查,而不仅仅是精确的类匹配。如果要映射的值是基类的子类

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实现映射器{
私有映射keyMappers=newhashmap();
私有映射valueMappers=newhashmap();
public void addMapper(映射器映射器、类keyClass、类valueClass){
keyMappers.put(keyClass,mapper);
valueMappers.put(valueClass,Mappers);
}
公共K图(V值){
Mapper Mapper=valueMappers.get(value.getClass());
返回mapper.map(值);
}
公共V映射反向(K键){
Mapper Mapper=keyMappers.get(key.getClass());
返回mapper.mapReverse(键);
}
}
或者通过提供类使映射方法“不那么神奇”,就像在代码中一样(MapperFacade不再实现映射器)

public K映射(V值,Class值Class){
Mapper Mapper=valueMappers.get(valueClass);
返回mapper.map(值);
}
公共V映射反向(K键,Class键Class){
Mapper Mapper=keyMappers.get(keyClass);
返回mapper.mapReverse(键);
}
这假设每个类有一个映射器。如果同一个类可能有多个映射器,则可能需要使用单个HashMap,但密钥需要使用一个bean,该bean由
或两个映射组成

    private Map<Class<K>,Map<Class<V>,Mapper<K,V>>> keyMappers = ...
    private Map<Class<V>,Map<Class<K>,Mapper<K,V>>> valueMappers = ...
私有映射键映射器=。。。
私有映射值映射程序=。。。

您正在重新实施番石榴。用那个

1) 如何在运行时和运行时获得适当的映射器实现 知道要调用哪个方法(map或mapReverse)

要在运行时探索元级别信息,可以尝试以下操作

它允许您在运行时“查询”类定义元数据:

Reflections reflections = new Reflections("my.project");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
Reflections=newreflections(“my.project”);

设置所以我最近自己用spring解决了这个问题。 这是解决办法

首先,将映射器接口重构为:-

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());
    }
}
公共抽象类映射器{
私有静态最终MapperFactory MapperFactory=MapperFactory.getInstance();
公共映射器(){
registerMapper(getEntityClass(),getDTOClass(),this);
}
公共抽象实体映射(DTO对象);
公共抽象数据到mapReverse(实体对象);
公共抽象类getEntityClass();
公共抽象类getDTOClass();
}
公共类MapperFactory{
private Map mappers=new ConcurrentHashMap();//MapperFactory是一个单例类,ConcurrentHashMap确保线程安全。
私有静态最终MapperFactory实例=新建MapperFactory();
公共静态MapperFactory(){
返回MapperFactory.INSTANCE;
}
公共无效注册表映射器(类entityClass、类dtoClass、映射器映射器){
put(dtoClass.getCanonicalName(),mapper);
put(entityClass.getCanonicalName(),mapper);
}
公共映射器getMapper(类sourceClass){
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);
    }
}
公共类MapperFacade{
私有MapperFactory MapperFactory=MapperFactory.getInstance();
公共DTO entityToDTO(实体,类dtoClass){
Mapper Mapper=mapperFactory.getMapper(entity.getClass());
返回mapper.mapReverse(实体);
}
公共实体dtoToEntity(DTO DTO,类entityClass){
Mapper Mapper=mapperFactory.getMapper(dto.getClass());
返回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();
    }
}
@组件
公共级卡马佩尔{
公共汽车地图(CarDTO CarDTO){
//恳求
}
公共卡至地图倒车(汽车){
//恳求
}
公共类getEntityClass(){
return Car.getClass();
}
公共类getDtoClass(){
返回CarDTO.getClass();
}
}

因此,现在您不必关心映射器类是什么,也不需要自己在一些初始化代码中注册它们。

我认为没有办法做到这一点。。但是您可以使用生成器类。。使用键和值类作为参数来构建..是否在某处保留一个
映射
?详细说明并称之为
MapperRegistry
?很多ORM都有这样一个门面:
Mapper=ORM.createDto(Car.class)
您似乎在寻找服务提供者接口。可能包括一个命令
@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();
    }
}