通过java.util.ServiceLoader加载通用服务实现

时间:2011-03-27 19:23:14

标签: java java-6

2 个答案:

答案 0 :(得分:6)

这里的问题是服务加载器正在使用列出给定类/接口的所有实现的文件,该文件由接口名称命名。没有预见到将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;
    }

}

这未经过测试,可能需要扩展到由我们的类直接实现的接口扩展的搜索接口,以及由我们的(通用)超类实现的接口。

当然,这只能找到像

这样的类
class Example implements Service<String> { ...}

不像

class Example<X> implements Service<X> { ... }

其中Example<String>可能是您服务的有效实施。

答案 1 :(得分:0)

您也可以只复制ServiceLoader类文件并从load()方法中删除泛型类型参数,使其始终有效。你只需要覆盖警告。

  public static <S> ServiceLoader load(final Class<S> service)
   {
      return load(service, Thread.currentThread().getContextClassLoader());
   }