Is something similar to ServiceLoader in Java 1.5?
Solution 1
There's nothing built into Java 1.5 for this. I implemented it myself; it's not too complicated. However, when we upgrade to Java 6, I will have to replace calls to my implementation with calls to ServiceLoader
. I could have defined a little bridge between the app and the loader, but I only use it in a few places, and the wrapper itself would be a good candidate for a ServiceLoader.
This is the core idea:
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;
}
Better exception handling is left as an exercise for the reader. Also, the method could be parameterized to accept a ClassLoader of the caller's choosing.
Solution 2
javax.imageio.spi.ServiceRegistry
is the equivalent with prior Java versions. It's available since Java 1.4.
It does not look like a general utility class, but it is. It's even a bit more powerful than ServiceLoader
, as it allows some control over the order of the returned providers and direct access to the registry.
See http://docs.oracle.com/javase/7/docs/api/index.html?javax/imageio/spi/ServiceRegistry.html
Solution 3
ServiceLoader is quite basic, and has been in use (informally) within the JDK since 1.3. ServiceLoader just finally made it a first class citizen. It simply looks for a resource file named for your interface, which is basically bundled in the META-INF directory of a library jar.
That file contains the name of the class to load.
So, you'd have a file named:
META-INF/services/com.example.your.interface
and inside it is a single line: com.you.your.interfaceImpl.
In lieu of ServiceLoader, I like Netbeans Lookup. It works with 1.5 (and maybe 1.4).
Out of the box, it does the exact same thing as ServiceLoader, and it's trivial to use. But it offers a lot more flexibility.
Here's a link: http://openide.netbeans.org/lookup/
Here's a article about ServiceLoader, but it mentions Netbeans Lookup at the bottom: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html
Solution 4
This is an old question but the other option is to use Package Level Annotations. See my answer for: Find Java classes implementing an interface
Package level annotations are annotations that are in package-info.java classes.
JAXB uses this instead of Service Loaders. I also think its more flexible than the service loader.
Solution 5
Unfortunately,
There's nothing built into Java 1.5 for this ...
is only a part of truth.
There is non-standard sun.misc.Service
around.
http://www.docjar.com/docs/api/sun/misc/Service.html
Beware, it is not a part of standard J2SE API!
It is non-standard part of Sun JDK.
So you can not rely on it if you use, say, JRockit
.
Comments
-
Alex Morega over 3 years
How do I discover classes at runtime in the classpath which implements a defined interface?
ServiceLoader suits well (I think, I haven't used it), but I need do it in Java 1.5.