How do I specify both an interface and its type parameters when requesting & referencing a service in OSGi DS?
I have an interface like:
interface Foo<T> {
void doSomethingWith(T t);
}
And some implementations like:
class Bar implements Foo<String> {
void doSomethingWith(String s) {开发者_StackOverflow社区
// ...
}
}
class Baz implements Foo<Double> {
void doSomethingWith(Double d) {
// ...
}
}
I have an OSGi service that needs an instance of a Foo<String> (and another service that needs a Foo<Double>, etc.).
Is there a way to expose & thus inject the implementations using Declarative Services? I can only figure out how to expose Bar & Baz as Foo & not as Foo<String> and Foo<Double>, respectively.
In short, there is no such thing as Foo<String>
at runtime due to the type Type Erasure. The type information is lost.
Instead, you can expose Bar
as raw Foo
with service property typeArg=java.lang.String
and use filter when injecting it to the consumer.
Other way is to introduce interfaces FooString extends Foo<String> { }
, FooDouble extends Foo<Double> { }
and use them instead of Foo
.
In the type Foo, T is erased to object. So the method on the interface is
void doSomethingWith(Object t)
When you define Bar as implements Foo<String>, you end up with two methods including the compiler generated synthetic bridge method which takes the type Object.
void doSomethingWith(Object t) {
doSomethingWith((String)t);
}
But as far as OSGi services are concerned, the type of a service registered under the name Foo is just Foo and any class that implements it must have a doSomethingWith(Object t) method. There is no way (other than you defining and using some service properties) for the framework or Declarative Service to understand the service implementation (e.g. Bar) has defined T to be String.
精彩评论