类似于Java 1.5中的ServiceLoader吗?
如何在实现定义接口的类路径中发现运行时的类?
ServiceLoader非常适合(我认为,我还没有使用它),但我需要在Java 1.5中使用它。
Java 1.5中没有内置任何内容。 我自己实施了; 这不是太复杂。 但是,当我们升级到Java 6时,我将不得不通过调用ServiceLoader
来替换对我的实现的调用。 我可以在应用程序和加载器之间定义一个小桥梁,但我只在几个地方使用它,并且包装器本身将是ServiceLoader的一个很好的候选者。
这是核心理念:
public Iterable load(Class ifc) throws Exception { ClassLoader ldr = Thread.currentThread().getContextClassLoader(); Enumeration e = ldr.getResources("META-INF/services/" + ifc.getName()); Collection services = new ArrayList(); 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; }
更好的exception处理留给读者练习。 此外,该方法可以参数化以接受调用者选择的ClassLoader。
javax.imageio.spi.ServiceRegistry
与以前的Java版本等效。 它从Java 1.4开始就可用。
它看起来不像一般的实用类,但确实如此。 它甚至比ServiceLoader
更强大,因为它允许对返回的提供程序的顺序进行一些控制并直接访问注册表。
请参阅http://docs.oracle.com/javase/7/docs/api/index.html?javax/imageio/spi/ServiceRegistry.html
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 Lookup: http : //weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html
这是一个老问题,但另一个选择是使用包级别注释 。 请参阅我的答案: 查找实现接口的Java类
包级别注释是package-info.java类中的注释。
JAXB使用它而不是服务加载器。 我也认为它比服务加载器更灵活。
不幸,
Java 1.5中没有内置任何内容……
只是真理的一部分。
周围有非标准的sun.misc.Service
。
http://www.docjar.com/docs/api/sun/misc/Service.html
请注意,它不是标准J2SE API的一部分! 它是Sun JDK的非标准部分。 因此,如果您使用JRockit
,则不能依赖它。
没有可靠的方法来了解类路径中的类。 根据其文档 ,ServiceLoader依赖外部文件来告诉它要加载哪些类; 你可能也想这样做。 基本思想是让一个文件具有要加载的类的名称,然后使用reflection来实例化它/它们。
您是否考虑过使用OSGI框架?