java绑定通用服务及其实现和子类型
免责声明:请接受我大量的代码来解释这个场景
在maven模块(核心)中,我们有以下几个类:
abstract class ReportingEvent {
}
abstract class Element {
public <E extends ReportingEvent> Optional<E> getReportEvent() {
return Optional.empty();
}
}
服务,例如:
public interface Reporting<E extends ReportingEvent> {
void report(E event);
}
interface InternalService {
}
public class InternalServiceImpl implements InternalService {
@Inject
Reporting<ReportingEvent> reporting; // 1. Possible to use a generic type? How?
private void reportEvents(BatchRequest batchRequest) {
batchRequest.stream()
// section below is of importance
.map(m -> m.getEntity().getReportEvent()) // the generic method from 'Element'
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(event -> reporting.report(event)); // method from 'Reporting'
}
}
class CoreBindingModule extends AbstractModule {
protected void configure() {
bind(InternalService.class).to(InternalServiceImpl.class).in(Singleton.class);
}
}
此外,在我们部署的另一个maven模块(consumer)中,我们有与上述功能相关并实现这些功能的类,如下所示:
abstract class BaseReporting extends ReportingEvent {
}
class ColdReporting extends BaseReporting {
}
abstract class Node extends Element {
}
class Cold extends Node {
@Override
public Optional<ColdReporting> getReportEvent() {
return Optional.ofNullable(new ColdReporting()); // some business logic
}
}
class ReportingImpl implements Reporting<ReportingEvent> { // 2. Use 'BaseReporting' here
void report(ReportingEvent event){}
}
class ConsumerBindingModule extends AbstractModule {
protected void configure() {
bind(new TypeLiteral<Reporting<ReportingEvent>>() {}).to(ReportingImpl.class).in(Singleton.class);
}
}
上面的代码运行良好。但问题是使用与模块不太相关的类型
A因此,如果我将使用者模块中的绑定更改为
bind(new TypeLiteral<Reporting<BaseReporting>>() {}).to(ReportingImpl.class).in(Singleton.class);
与
class ReportingImpl implements Reporting<BaseReporting> {
void report(BaseReporting event){}
}
我犯了个错误
No implementation for Reporting<ReportEvent> was bound. while locating Reporting<ReportEvent> for field at InternalServiceImpl.reporting(InternalServiceImpl.java:21)
这是相关的,我无论如何也不能在核心模块中使用Reporting<BaseReporting>
B另一方面,如果我尝试将Reporting
注入为:
@Inject
Reporting<? extends ReportingEvent> reporting;
然后想法陈述
Required type: capture of ? Provided: ReportingEvent
在线上
...forEach(event -> reporting.report(event))
在试图解决代码部分提到的1和2问题时,有没有办法避开这种情况
# 1 楼答案
(我可能在重复你大部分已经知道的内容)
撇开与GUI相关的模块和配置不谈,您的问题可以写为
这和
比如说,你有一个
HotReporting
类,它扩展了BaseReporting
,所以你有这样的东西假设您为
Reporting<? extends ReportingEvent> reporting
字段注入了HotReportingImpl
在代码中,如果
m.getEntity().getReportEvent()
返回一个ColdReporting
怎么办?它与这里的report
方法所期望的(aHotReporting
)不兼容选项1:
我会尝试去掉泛型类型参数,并将
Reporting
定义为问题:
ReportingEvent
的确切子类型(需要类型转换,这不好)李>HotReportingImpl
仍然可以获取ColdReporting
对象作为参数李>选项2:
通过向
InternalService
中添加类型参数,可以使其成为泛型的如果实现
Reporting
的类必须处理ReportingEvent
的具体类型,那么Element
返回基类型(ReportingEvent
)似乎是不对的看看Typesafe heterogeneous containers by Joshua Bloch。你的问题与此重叠。可以使用该类型参数维护从
ReportingEvent
类型到Reporting
相应子类的映射