2008-10-30 67 views

回答

18

Java 1.5中没有内置任何内容。我自己实现了它;它不是太复杂。但是,当我们升级到Java 6时,我将不得不使用调用ServiceLoader来替换对我的实现的调用。我本可以在应用程序和加载器之间定义一个小桥梁,但我只在几个地方使用它,而封装器本身就是ServiceLoader的一个很好的候选者。

这是核心思想是:

public <S> Iterable<S> load(Class<S> ifc) throws Exception { 
    ClassLoader ldr = Thread.currentThread().getContextClassLoader(); 
    Enumeration<URL> e = ldr.getResources("META-INF/services/" + ifc.getName()); 
    Collection<S> services = new ArrayList<S>(); 
    while (e.hasMoreElements()) { 
    URL url = e.nextElement(); 
    InputStream is = url.openStream(); 
    try { 
     BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8")); 
     while (true) { 
     String line = r.readLine(); 
     if (line == null) 
      break; 
     int comment = line.indexOf('#'); 
     if (comment >= 0) 
      line = line.substring(0, comment); 
     String name = line.trim(); 
     if (name.length() == 0) 
      continue; 
     Class<?> clz = Class.forName(name, true, ldr); 
     Class<? extends S> impl = clz.asSubclass(ifc); 
     Constructor<? extends S> ctor = impl.getConstructor(); 
     S svc = ctor.newInstance(); 
     services.add(svc); 
     } 
    } 
    finally { 
     is.close(); 
    } 
    } 
    return services; 
} 

更好的异常处理是作为练习留给读者。另外,该方法可以被参数化为接受调用者选择的ClassLoader。

0

没有可靠的方法来知道类路径中的类是什么。根据其documentation,ServiceLoader依靠外部文件来告诉它要加载哪些类;你可能想要做同样的事情。基本的想法是用一个文件加载类的名字,然后用反射来实例化它/它们。

1

ServiceLoader是相当基本的,自1.3版以来一直在JDK中使用(非正式)。 ServiceLoader终于使它成为一流的公民。它只是寻找一个为你的接口命名的资源文件,它基本上捆绑在库jar的META-INF目录中。

该文件包含要加载的类的名称。

所以,你有一个名为文件:

META-INF /服务/ com.example.your.interface

和里面是一个单行:com.you.your.interfaceImpl 。

代替ServiceLoader,我喜欢Netbeans Lookup。它适用于1.5(也许1.4)。

开箱即用,它与ServiceLoader完全相同,使用起来也很简单。但它提供了更多的灵活性。

这里有一个链接:http://openide.netbeans.org/lookup/

这里有一个大约的ServiceLoader的文章,但它提到的Netbeans查找在底部: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html

-1

你有没有想过使用OSGi框架的?

1

不幸的是,

没有什么内置的Java 1.5此...

是唯一的真理的一部分。

周围有非标准sun.misc.Service

http://www.docjar.com/docs/api/sun/misc/Service.html

当心,这不是标准的J2SE API的一部分! 这是Sun JDK的非标准部分。 所以,如果你使用JRockit,那么你不能依赖它。

1

这是一个老问题,但另一种选择是使用包级别注释。 查看我的联系方式:Find Java classes implementing an interface

软件包级别注释是package-info.java类中的注释。

JAXB使用此代替服务加载器。我也认为它比服务加载器更灵活。