前几天我偶然发现了一些不便,java.util.ServiceLoader并在我身上形成了一些问题.
假设我有一个通用服务:
public interface Service<T> { ... }
Run Code Online (Sandbox Code Playgroud)
我无法明确告诉只ServiceLoader加载具有特定泛型类型的实现.
ServiceLoader<Service<String>> services =
ServiceLoader.load(Service.class); // Fail.
Run Code Online (Sandbox Code Playgroud)
我的问题是:什么是合理的方法ServiceLoader来安全地加载通用服务的实现?
在询问了上述问题之后,在Paŭlo的回答之前,我已经设法找到了解决方案.
public interface Service<T> { ...
// true if an implementation can handle the given `t' type; false otherwise.
public boolean canHandle(Class<?> t) { ...
public final class StringService implements Service<String> { ...
@Override public boolean canHandle(Class<?> t) {
if (String.class.isAssignableFrom(type))
return true;
return false;
}
public final class DoubleService implements Service<Double> { ...
// ...
public final class Services { ...
public static <T> Service<T> getService(Class<?> t) {
for (Service<T> s : ServiceLoader.load(Service.class))
if (s.canServe(t))
return s;
throw new UnsupportedOperationException("No servings today my son!");
}
Run Code Online (Sandbox Code Playgroud)
boolean canServe(Class<?> t)以相同的方式改变boolean canServe(Object o)和改变<T> Service<T> getService(Class<?> t)可以更加动态(我自己使用后者,因为我boolean canHandle(T t)在开始时在我的界面上有一个方法.)
这里的问题是服务加载器正在使用列出给定类/接口的所有实现的文件,该文件由接口名称命名.没有预见到将type参数放入此文件名中,并且实际上也不可能将泛型类型作为Class对象传递.
所以,你在这里只能得到任何类型的通用服务,然后检查它们的类对象,看它是否是一个子类型Service<String>.
像这样的东西:
class Test{
public Service<String> getStringService() {
// it is a bit strange that we can't explicitely construct a
// parametrized type from raw type and parameters, so here
// we use this workaround. This may need a dummy method or
// variable if this method should have another return type.
ParametrizedType stringServiceType =
(ParametrizedType)Test.class.getMethod("getStringService").getGenericReturnType();
ServiceLoader<Service<?>> loader = ServiceLoader.load(Service<?>.class);
for(Service<?> service : loader) {
if(isImplementing(service.getClass(), stringServiceType)) {
@SuppressWarnings("unchecked")
Service<String> s = (Service)service;
return s;
}
}
}
public boolean isImplementing(Class<?> candidate, ParametrizedType t) {
for(Type iFace : candidate.getGenericInterfaces()) {
if(iFace.equals(t)) {
return true;
}
if(iFace instanceof ParametrizedType &&
((ParametrizedType)iFace).getRawType().equals(t.getRawType())) {
return false;
}
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
这没有经过测试,可能需要扩展到我们的类直接实现的接口扩展的搜索接口,以及由我们的(通用)超类实现的接口.
当然,这只能找到类似的课程
class Example implements Service<String> { ...}
Run Code Online (Sandbox Code Playgroud)
不喜欢
class Example<X> implements Service<X> { ... }
Run Code Online (Sandbox Code Playgroud)
哪里Example<String>可能是您服务的有效实施.
| 归档时间: |
|
| 查看次数: |
5610 次 |
| 最近记录: |