如何基于泛型类型自动连接?



我有一个spring应用程序,它处理两种类型的对象——订单和错误。这两种类型的对象的大部分处理是相同的,但它们是从不同的表中查询的。因此,我做了这样的操作

@Service
public class MyService {
private final Processor<Order> orderProcessor;
private final Processor<Fault> faultProcessor;
public MyService(Processor<Order> orderProcessor, Processor<Fault> faultProcessor) {
this.orderProcessor = orderProcessor;
this.faultProcessor = faultProcessor;
}

public void process(Map<String, List<BaseEntity>> input) {

orderProcessor.process(input.get("ORDERS"));
faultProcessor.process(input.get("FAULTS"));
}
}

我的处理器实现看起来像

@Service
public class Processor<U extends BaseEntity> {
private final BaseRespository<U> repository;
public Processor(BaseRespository<U> repository) {
this.repository = repository;
}
public void process() {
//query the repository and do something
}
}

我的仓库是

@NoRepositoryBean
public interface BaseRepository<T extends BaseEntity> extends CrudRepository<T, Key> {
@Transactional
List<T> findAll(String id);
}
@Repository("order")
public interface OrderRepository extends BaseRepository<Order> {}
@Repository("fault")
public interface FaultRepository extends BaseRepository<Fault> {}

然而,当我启动应用程序时,它失败了,说"处理器的构造函数需要一个bean,但是找到了两个"。这里的问题是什么?我正在使用Spring Boot 2.7.0/Spring 5.3.2

您需要使用@Qualifier注释

@Service
public class MyService {
private final Processor<Order> orderProcessor;
private final Processor<Fault> faultProcessor;
public MyService(@Qualifier("order") Processor<Order> orderProcessor, @Qualifier("fault") Processor<Fault> faultProcessor) {
this.orderProcessor = orderProcessor;
this.faultProcessor = faultProcessor;
}

public void process(Map<String, List<BaseEntity>> input) {

orderProcessor.process(input.get("ORDERS"));
faultProcessor.process(input.get("FAULTS"));
}
}

注释告诉Spring使用Repository@Qualifer注释中提供的名称。既然您用@Repository("order")注释了orderRepository,那么@Qualifier("order")将告诉Spring使用该存储库。


编辑

Spring,像Java中的其他任何东西一样,不能将接口分配给接口。例如,下面的代码不能编译

private List<String> stringList = new List<String>();

这是因为实例化的值必须是有效的实现。您可以使用进一步的抽象和/或设计模式来解决这个问题。看一看工厂模式和/或策略模式,了解如何更有效地实现它们。或者,您可以尝试使用提供者在内部处理流程请求。

新支持接口

public interface Processes<T>
{
boolean processes(T object);
}
处理器

@Service
public abstract class Processor<U extends BaseEntity> implements Processes<Object>
{
public abstract void process(U entity);
}
实施

@Service
public class OrderProcessor extends Processor<Order>
{
@Qualifier("order")
BaseRepository<Order> repository;
public OrderProcessor(BaseRepository<Order> repository)
{
this.repository = repository;
}
@Override
public boolean supports(Object object)
{
return object instanceof Order;
}
@Override
public void process(Order order)
{
/// ... do process stuff
}
}

Spring Autowired List with Provider

@Service
public static class ProcessorProvider
{
@Autowired
List<Processor<? extends BaseEntity>> processors;
public <T extends BaseEntity> void process(T type)
{
var processor = processors.stream().filter(proc -> proc.processes(type)).findFirst();
processor.ifPresent(proc -> process(proc, type));
}
private <T extends BaseEntity> void process(Processor<? extends BaseEntity> processor, T type)
{
if (processor instanceof OrderProcessor) {
((OrderProcessor) processor).process((Order) type);
}
else if (processor instanceof FaultProcessor) {
((FaultProcessor) processor).process((Fault) type);
}
}
}

现在你可以从你的实现代码中调用ProcessorProvider

@Service
public class MyService {

SpringscratchApplication.ProcessorProvider provider;
public MyService(SpringscratchApplication.ProcessorProvider provider) {
this.provider = provider;
}
public void process(Map<String, List<BaseEntity>> input) {
input.get("ORDERS").forEach(order -> provider.process(order));
input.get("FAULTS").forEach(order -> provider.process(order));
}
}

相关内容

最新更新