优化从实现同一接口的各Service中调用方法的方案
简化多Shape服务并行查询的实现方案
你当前通过自定义ShapeTask实现并行查询各Shape仓库数据,但新增方法时需要重复创建对应Task类,导致冗余代码过多。下面是几种简化方案,既能保留并行查询能力,又能大幅降低后续扩展的成本。
方案1:用CompletableFuture替代自定义Task
Java 8引入的CompletableFuture可以直接通过方法引用创建异步任务,无需手动实现Callable接口,完全去掉ShapeTask类,简化代码结构。
修改后的TestService代码:
@Service @RequiredArgsConstructor public class TestService { private final ShapeServiceFacade facade; private final ExecutorService executorService; public List<ShapeEntity> getAll() throws ExecutionException, InterruptedException { List<CompletableFuture<List<ShapeEntity>>> futures = facade.getServices().stream() .map(service -> CompletableFuture.supplyAsync(service::getAll, executorService)) .toList(); // 等待所有任务完成并合并结果 return futures.stream() .map(CompletableFuture::join) .flatMap(List::stream) .collect(Collectors.toList()); } }
说明:
- 用
CompletableFuture.supplyAsync结合方法引用service::getAll,替代自定义的ShapeTask - 流式API简化集合操作,减少冗余循环代码
join()方法等价于future.get(),但无需显式处理受检异常(可全局捕获处理)
方案2:将通用并行逻辑封装到Facade
把并行执行逻辑封装到ShapeServiceFacade中,新增方法时仅需在Facade中添加包装方法,无需修改调用端代码,彻底解决扩展时的重复劳动问题。
修改后的ShapeServiceFacade:
@Service public class ShapeServiceFacade { private final Map<String, ShapeServicesInterface> shapeServices; private final ExecutorService executorService; // 注入所有Shape服务和线程池 public ShapeServiceFacade(Set<ShapeServicesInterface> allServices, ExecutorService executorService) { this.shapeServices = allServices.stream() .collect(Collectors.toMap(ShapeServicesInterface::getName, Function.identity())); this.executorService = executorService; } public List<ShapeServicesInterface> getServices() { return new ArrayList<>(shapeServices.values()); } // 通用并行执行模板方法,接收方法引用即可执行对应逻辑 private <T> List<T> executeParallel(Function<ShapeServicesInterface, List<T>> methodExtractor) { return getServices().stream() .map(service -> CompletableFuture.supplyAsync(() -> methodExtractor.apply(service), executorService)) .map(CompletableFuture::join) .flatMap(List::stream) .collect(Collectors.toList()); } // 对应原有的getAll方法 public List<ShapeEntity> getAllShapes() { return executeParallel(ShapeServicesInterface::getAll); } // 新增方法示例:获取所有激活状态的Shape public List<ShapeEntity> getActiveShapes() { return executeParallel(ShapeServicesInterface::getActive); } }
简化后的TestService:
@Service @RequiredArgsConstructor public class TestService { private final ShapeServiceFacade facade; public List<ShapeEntity> getAll() { return facade.getAllShapes(); } // 新增方法直接调用Facade封装好的逻辑 public List<ShapeEntity> getActive() { return facade.getActiveShapes(); } }
扩展流程:
- 在
ShapeServicesInterface中新增方法(如List<ShapeEntity> getActive();) - 在各Service实现类中实现该方法
- 在
ShapeServiceFacade中添加调用executeParallel的包装方法即可
完全无需创建新的Task类,也不用修改调用端逻辑,扩展成本极低。
方案3:Spring环境下用@Async注解简化(可选)
如果项目基于Spring,可以利用@Async注解自动处理异步逻辑,无需手动管理线程池:
- 开启异步支持:
@Configuration @EnableAsync public class AsyncConfig { @Bean public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(4); executor.setMaxPoolSize(8); executor.setQueueCapacity(100); executor.setThreadNamePrefix("ShapeAsync-"); executor.initialize(); return executor; } }
- 修改接口方法为异步返回:
public interface ShapeServicesInterface { @Async CompletableFuture<List<ShapeEntity>> getAll(); String getName(); }
- 实现类无需额外修改:
@Service @RequiredArgsConstructor public class CircleEntityService implements ShapeServicesInterface { private final CircleEntityRepository circleEntityRepository; @Override public CompletableFuture<List<ShapeEntity>> getAll() { return CompletableFuture.completedFuture(new ArrayList<>(circleEntityRepository.findAll())); } @Override public String getName() { return "circle"; } }
- 调用端简化:
@Service @RequiredArgsConstructor public class TestService { private final ShapeServiceFacade facade; public List<ShapeEntity> getAll() { return facade.getServices().stream() .map(ShapeServicesInterface::getAll) .map(CompletableFuture::join) .flatMap(List::stream) .collect(Collectors.toList()); } }
这种方式由Spring统一管理异步任务,无需手动处理线程池,适合Spring环境下的快速开发。
内容的提问来源于stack exchange,提问作者Lulex97
相关产品推荐
相关产品推荐

