2008-10-30 24 views

Respuesta

18

No hay nada incorporado 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 al 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; 
} 

mejor manejo de excepciones se deja como 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.

0

No hay una manera confiable de saber qué clases están en la ruta de clase. De acuerdo con su documentation, 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.

1

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.

Por lo tanto, tendría un archivo llamado:

META-INF/services/com.example.your.interface

y en su interior 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í está un artículo sobre ServiceLoader, pero menciones Netbeans de búsqueda en la parte inferior: http://weblogs.java.net/blog/timboudreau/archive/2008/08/simple_dependen.html

-1

ha pensado en utilizar un framework OSGi?

1

Desafortunadamente,

No hay nada construido en Java 1.5 para este ...

es sólo una parte de la verdad.

No es estándar sun.misc.Service alrededor.

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

ten cuidado, que no es una parte de la API de J2SE estándar! Es una parte no estándar de Sun JDK. Así que no puede confiar si usa, digamos, JRockit.

1

Esta es una pregunta anterior, pero la otra opción es usar Anotaciones de nivel de paquete. Ver mi respuesta para: Find Java classes implementing an interface

Las anotaciones a nivel de paquete son anotaciones que están en las clases package-info.java.

JAXB utiliza esto en lugar de Service Loaders. También creo que es más flexible que el cargador de servicios.

Cuestiones relacionadas