¿Hay algo similar a ServiceLoader en Java 1.5?
reflection plugins (7)
No hay una manera confiable de saber qué clases están en el classpath. De acuerdo con su documentación , ServiceLoader se basa en archivos externos para indicarle qué clases cargar; es posible que desee hacer lo mismo. La idea básica es tener un archivo con el nombre de la (s) clase (s) a cargar, y luego usar el reflejo para crear una instancia de ellos / ellos.
¿Cómo descubro las clases en tiempo de ejecución en el classpath que implementa una interfaz definida?
ServiceLoader se adapta bien (creo que no lo he usado), pero necesito hacerlo en Java 1.5.
ServiceLoader es bastante básico, y ha estado en uso (informalmente) dentro del JDK desde 1.3. ServiceLoader finalmente lo convirtió en un ciudadano de primera clase. Simplemente busca un archivo de recursos con el nombre de su interfaz, que básicamente se incluye en el directorio META-INF de un archivo jar de la biblioteca.
Ese archivo contiene el nombre de la clase a cargar.
Entonces, tendrías un archivo llamado:
META-INF / services / com.example.your.interface
y dentro de ella hay una sola línea: com.you.your.interfaceImpl.
En lugar de ServiceLoader, me gusta Netbeans Lookup. Funciona con 1.5 (y tal vez 1.4).
Fuera de la caja, hace exactamente lo mismo que ServiceLoader, y es trivial de usar. Pero ofrece mucha más flexibilidad.
Aquí hay un enlace: http://openide.netbeans.org/lookup/
Aquí hay un artículo sobre ServiceLoader, pero menciona la búsqueda de Netbeans en la parte inferior: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html
No hay nada integrado en Java 1.5 para esto. Lo implementé yo mismo; no es muy complicado. Sin embargo, cuando actualicemos a Java 6, tendré que reemplazar las llamadas a mi implementación con llamadas a ServiceLoader
. Podría haber definido un pequeño puente entre la aplicación y el cargador, pero solo lo uso en algunos lugares, y el contenedor podría ser un buen candidato para un ServiceLoader.
Esta es la idea central:
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;
}
Un mejor manejo de excepciones se deja como un ejercicio para el lector. Además, el método podría parametrizarse para aceptar un ClassLoader de la elección de la persona que llama.
¿Has pensado en usar un marco OSGI?
Desafortunadamente,
No hay nada integrado en Java 1.5 para esto ...
es solo una parte de la verdad
No hay sun.misc.Service
no estándar alrededor.
http://www.docjar.com/docs/api/sun/misc/Service.html
¡Cuidado, no es parte de la API J2SE estándar! Es una parte no estándar de Sun JDK. Entonces no puedes confiar en él si usas, digamos, JRockit
.
javax.imageio.spi.ServiceRegistry
es el equivalente con versiones anteriores de Java. Está disponible desde Java 1.4.
No parece una clase de utilidad general, pero lo es. Incluso es un poco más potente que ServiceLoader
, ya que permite cierto control sobre el orden de los proveedores devueltos y el acceso directo al registro.
Ver http://docs.oracle.com/javase/7/docs/api/index.html?javax/imageio/spi/ServiceRegistry.html
Esta es una pregunta antigua, pero la otra opción es usar anotaciones de nivel de paquete . Ver mi respuesta para: Buscar clases Java implementando una interfaz
Las anotaciones de nivel de paquete son anotaciones que están en clases package-info.java.
JAXB usa esto en lugar de Service Loaders. También creo que es más flexible que el cargador de servicios.