java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > 通过Interface扫描获取所有实现类

通过Interface扫描获取所有实现类方式

作者:码上走人

文章介绍了如何使用ClassPathScanningCandidateComponentProvider从指定包中扫描接口实现类,并通过接口统一管理和获取实现对象,这种方法避免了手动创建对象和修改代码的问题,并且可以处理链路方式下的多处理器顺序处理

通过Interface扫描获取所有实现类

当我们在代码中定义了一个接口,很多功能累实现了这个接口。所以我们可以统一管理这个接口,避免自己手动创建对象。避免在后续的新功能假如是实现时修改过多的代码,而导致意外出现。

ClassPathScanningCandidateComponentProvider 提供了一个从指定包中扫面接口实现类的功能。

ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(BaseHandler.class));
Set<BeanDefinition> definitionSet = provider.findCandidateComponents("com.test.xxxx.handler");
for (BeanDefinition beanDefinition : definitionSet) {
      Class<?> clazz = Class.forName(beanDefinition.getBeanClassName());
      LOGGER.info("初始化数据同步处理service:{}", beanDefinition.getBeanClassName());
      BaseHandler handler= (BaseHandler) clazz.newInstance();
      
       //其他的业务逻辑,可以用map统一管理
       //例如接口中加如一个方法,强制实现类实现,并给出自己的唯一Id
       HandlerDto handlerDto = service.getUnique();
        
}

这样我们就可以获取到所有的实现类并在需要的时候,传入参数获取其对象。

完整实现测试

如下所示:

接口

public interface BaseHandler {

    /**
     * 获取处理器的唯一编码  
     */
    DataHandlerDto getUnique();

    /**
     * 业务实现逻辑
     */
    void dealData(Object obj);
}

统一管理和获取实现对象

@Component
public class HnadlerManager {

    public static final Map<HandlerDto, Class< ? extends BaseHandler>> HANDLER_SERVICE_MAP = new HashMap<>();


    @PostConstruct
    private static void initOperateService(){
        LOGGER.info("初始化数据同步处理handler");
        registerCollect();
    }

    private static void registerCollect(){
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AssignableTypeFilter(BaseHandler.class));
        Set<BeanDefinition> definitionSet = provider.findCandidateComponents("com.eshore.cnomp.handler");
        try {
            for (BeanDefinition beanDefinition : definitionSet) {
                Class<?> clazz = Class.forName(beanDefinition.getBeanClassName());
                LOGGER.info("初始化数据同步处理service:{}", beanDefinition.getBeanClassName());
                BaseHandler service = (BaseHandler) clazz.newInstance();
                HandlerDto handlerDto = service.getUnique();
                boolean iscontain = false;
                for(Map.Entry<HandlerDto,Class< ? extends BaseHandler>> entry: HANDLER_SERVICE_MAP.entrySet()){
                    HandlerDto dto = entry.getKey();
                    if(dto.getId.equals(handlerDto.getId())){
                        iscontain = true;
                        LOGGER.info("已存在相同数据同步处理类:{}, {}",entry.getValue().getName(), JSON.toJSONString(dto));
                    }
                }

                if(!iscontain){
                    HANDLER_SERVICE_MAP.put(HandlerDto, service.getClass());
                }
            }
        }catch (Exception e){
            LOGGER.error("初始化数据同步处理service失败", e);
            throw new RuntimeException("初始化数据同步处理service失败");
        }
    }

    public static BaseHandler getHandler(String id){
        for(Map.Entry<HandlerDto,Class< ? extends BaseHandler>> entry: HANDLER_SERVICE_MAP.entrySet()){
            HandlerDto dto = entry.getKey();
            if(dto.getId.equals(id)){
                Class<? extends BaseHandler> clazz = entry.getValue();
                try {
                    return clazz.newInstance();
                } catch (Exception e) {
                    LOGGER.error("构建采集兑现失败", e);
                    return null;
                }
            }
        }
        return null;
    }

}

以上实现是单个兑现的实现。

如果需要以链路的方式,即同一个对象可以被多个处理器顺序处理,则需要调整其存储的方式为list并加入排序。

总结

这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文