通过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并加入排序。
总结
这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
