Java 在请求&;时,如何指定接口及其类型参数;在OSGi DS中引用服务?

Java 在请求&;时,如何指定接口及其类型参数;在OSGi DS中引用服务?,java,generics,osgi,Java,Generics,Osgi,我有这样一个界面: interface Foo<T> { void doSomethingWith(T t); } 接口Foo{ 无效剂量(T); } 还有一些实现,如: class Bar implements Foo<String> { void doSomethingWith(String s) { // ... } } class Baz implements Foo<Double> { void

我有这样一个界面:

interface Foo<T> {
    void doSomethingWith(T t);
}
接口Foo{
无效剂量(T);
}
还有一些实现,如:

class Bar implements Foo<String> {
    void doSomethingWith(String s) {
        // ...
    }
}

class Baz implements Foo<Double> {
    void doSomethingWith(Double d) {
        // ...
    }
}
类栏实现了Foo{
void doSomethingWith(字符串s){
// ...
}
}
类Baz实现了Foo{
无效剂量(双d){
// ...
}
}
我有一个OSGi服务需要一个Foo实例(还有另一个服务需要一个Foo,等等)


有没有一种方法可以使用声明性服务公开并注入实现?我只知道如何将Bar&Baz分别公开为Foo&而不是Foo和Foo。

简而言之,由于类型不同,在运行时不存在
Foo
。类型信息丢失

相反,您可以使用服务属性
typeArg=java.lang.String
Bar
作为原始
Foo
公开,并在将其注入消费者时使用过滤器


另一种方法是引入接口
FooString扩展Foo{}
FooDouble扩展Foo{}
,并使用它们来代替
Foo
。简而言之,由于类型的原因,在运行时没有
Foo
这样的事情。类型信息丢失

相反,您可以使用服务属性
typeArg=java.lang.String
Bar
作为原始
Foo
公开,并在将其注入消费者时使用过滤器


另一种方法是引入接口
FooString扩展Foo{}
FooDouble扩展Foo{}
,并使用它们代替Foo类型中的
Foo
,,T被擦除为对象。因此,接口上的方法是

void doSomethingWith(Object t)
当您将Bar定义为implements Foo时,您将得到两个方法,包括采用类型对象的编译器生成的合成桥方法

void doSomethingWith(Object t) {
    doSomethingWith((String)t);
}

但就OSGi服务而言,以Foo名称注册的服务的类型就是Foo,实现它的任何类都必须具有doSomethingWith(Object t)方法。框架或声明性服务无法(除了您定义和使用一些服务属性)理解服务实现(如Bar)已将T定义为字符串。

在类型Foo中,T被擦除为对象。因此,接口上的方法是

void doSomethingWith(Object t)
当您将Bar定义为implements Foo时,您将得到两个方法,包括采用类型对象的编译器生成的合成桥方法

void doSomethingWith(Object t) {
    doSomethingWith((String)t);
}

但就OSGi服务而言,以Foo名称注册的服务的类型就是Foo,实现它的任何类都必须具有doSomethingWith(Object t)方法。框架或声明性服务无法(除了您定义和使用一些服务属性)理解服务实现(如Bar)已将T定义为字符串。

<和>因格式设置而丢失。<和>因格式设置而丢失。这是真的,但是Bar和Baz的类型参数化可以通过java.lang.reflect获得。我一直在使用FooString和FooDouble接口思想,但我不喜欢它们只是标记接口。我最终使用了这两种技术:添加一个
type=a
服务属性用于动态查找,以及添加标记接口用于DS注入(当静态知道捆绑包需要什么时)。这是真的,但是Bar和Baz的类型参数化可以通过java.lang.reflect获得。我一直在使用FooString和FooDouble接口思想,但我不喜欢它们只是标记接口。我最终使用了这两种技术:添加一个
type=a
服务属性进行动态查找,以及在静态知道捆绑包需要什么时为DS注入添加标记接口。框架或声明性服务实现可以使用java.lang.reflect确定服务实现将T定义为什么。通过反射并不总是可能做到这一点。例如,如果您有Baz实现Foo{};Foo Foo=new Baz();,如果我没有弄错的话,就没有办法在运行时找出T是什么。即使这是可能的,也可能不是那么简单。可能需要跟踪整个层次结构以找出实际参数,如:Bar实现Foo;Baz扩展了Bar等。这是真的,但我无法想象类型参数如何通过DS上下文中的反射而不被发现。DS无法通过检查ServiceReference来确定T的类型。DS可以使用客户机包的类加载器来查看类型Foo(服务的声明类型)具有正式类型T,但是DS如何确定客户机包期望的T值呢?DS可以让每个Foo服务对象(作为打破惰性的代价)检查T的实际类型,但不知道如何确定客户端所需的T的类型,这不是很有用。框架或声明性服务实现可以使用java.lang.reflect来确定服务实现将T定义为什么。通过反射并不总是可以做到这一点。例如,如果您有Baz实现Foo{};Foo Foo=new Baz();,如果我没有弄错的话,就没有办法在运行时找出T是什么。即使这是可能的,也可能不是那么简单。可能需要跟踪整个层次结构以找出实际参数,如:Bar实现Foo;Baz扩展了Bar等。这是真的,但我无法想象类型参数如何通过DS上下文中的反射而不被发现。DS无法通过检查ServiceReference来确定T的类型。DS可以使用客户机包的类加载器来查看类型Foo(服务的声明类型)具有正式类型T,但是DS如何确定客户机包期望的T值呢?DS可以让每个Foo服务对象(作为打破惰性的代价)检查T的实际类型,但不知道如何确定