2009-12-24 13 views

Respuesta

14

Si ServiceLoader se ajusta principalmente a sus necesidades, eso significa que está buscando descubrimiento de servicio a través de la presencia de archivos en la ruta de clase. Eso es solo una pequeña parte de lo que OSGi proporciona.

OSGi le permitirá instalar paquetes dinámicamente, anunciar servicios, revocar anuncios y desinstalar paquetes mientras se ejecuta la aplicación. Además, como consumidor de servicios, puede buscarlos ansiosamente (con filtrado de consultas de predicados) y detectar cuándo van y vienen los proveedores de servicios ofrecidos. Estos paquetes no necesitan estar en la ruta de clase, y se pueden proporcionar de varias formas; Jar archivos y "directorios explotados" son los dos que recuerdo. Por ejemplo, ServiceLoader hace una sola cosa: expone las fábricas detectables. Por lo general, creará una interfaz de fábrica que tome algún argumento para decidir si ese proveedor puede ofrecer el servicio adecuado, como asignar un nombre de conjunto de caracteres dado a CharsetDecoder. No existe un protocolo formalizado para adquirir y liberar un servicio de dicho proveedor. OSGi formaliza la vinculación y desvinculación de los consumidores a los servicios. El consumidor puede recibir una notificación cuando los nuevos proveedores entran en línea, y el proveedor puede recibir una notificación cuando el consumidor adquiera y libere una instancia de servicio. Si este control del ciclo de vida es importante para su servicio y renuncia a OSGi, tendrá que construirlo usted mismo; ServiceLoader no llega tan lejos.

De forma alternativa, en lugar de la búsqueda y el uso del servicio, puede adoptar un enfoque más pasivo y declarativo y dejar que uno de los administradores de dependencias OSGi coincida con sus necesidades indicadas con los proveedores de servicios disponibles. Hay muchos administradores de dependencia para elegir. Spring Dynamic Modules es uno de los más capaces.

OSGi proporciona muchas otras instalaciones de "middleware". No intentaré venderte aquí, ya que tu pregunta se centra principalmente en lo que te estarías perdiendo al elegir ServiceLoader.

+0

Gracias - siempre es difícil saber realmente qué es OSGi.No, realmente solo necesito lo que ServiceLocator tiene, y agradezco que esté integrado. Solo sospeché que no había oído hablar de él antes de pensar que debía estar enfermo o algo así. –

+2

Utilizo 'ServiceLoader' en un proyecto actual, y las únicas frustraciones que he encontrado son 1) con la necesidad de insertar extensiones como archivos Jar en la ruta de clase (nuestras aplicaciones no alientan a los usuarios finales a manipular la ruta de clases) y 2) el orden no especificado por el cual los proveedores hermanos de la misma interfaz de servicio estarán expuestos a un consumidor. Esto último hace que sea difícil incorporar una "prioridad", como que las extensiones proporcionadas por el usuario sean preferibles a los servicios básicos de la aplicación. Por lo tanto, 'ServiceLoader' se usa mejor cuando los proveedores no se superponen ni compiten entre sí. – seh

3

Como seh señala, si solo está interesado en la detección simple de servicios, entonces ServiceLoader es una forma ligera de separar a los consumidores de los proveedores. Pero no ofrece ninguna asistencia para componer servicios juntos.

Por ejemplo, supongamos que el servicio A necesita usar el servicio B. Esto es una "dependencia del servicio" ... pero ¿qué debe hacer A si B no está disponible? En OSGi podemos arreglar que si B no está disponible, entonces ninguno será A - asumiendo que la dependencia es obligatoria; también podemos admitir dependencias opcionales. Por otro lado, al usar ServiceLoader, el servicio A no tiene control sobre su disponibilidad, siempre y cuando el archivo JAR que lo contiene esté en la ruta de clase ... por lo que debe proporcionar su funcionalidad incluso en ausencia de los servicios necesarios de "back-end".

Otra cosa a tener en cuenta con ServiceLoader es intentar abstraer el mecanismo de búsqueda. El mecanismo de publicación es bastante agradable y limpio y declarativo. Pero la búsqueda (a través de java.util.ServiceLoader) es tan fea como el infierno, implementada como un escáner classpath que se rompe horriblemente si se coloca el código en cualquier entorno (como OSGi o Java EE) que no tenga visibilidad global. Si su código se enreda con eso, entonces tendrá dificultades para ejecutarlo en OSGi más adelante. Mejor escribir una abstracción que puedas reemplazar cuando llegue el momento.

+1

¿Puede ampliar una simple abstracción para ServiceLoader que facilitaría la migración a OSGi más adelante? Actualmente tengo un marco que se divide en 12 o 13 archivos jar que usan el mecanismo del cargador de recursos para que el componente central 'escanee' los módulos en el classpath. Deseo que el framework funcione bien en OSGi en el futuro pero no depender de OSGi. Hasta ahora, no puedo ver cómo lograr la dualidad. ¿Es posible incluso estar medio dentro y fuera de OSGi cuando se utiliza el mecanismo de ServiceLoader? – Chris

+1

La mejor abstracción sería algo así como la inyección de dependencia. En su código que requiere algún servicio "Foo", no intente buscar ese servicio, sino simplemente permita que se lo inyecte a través de un método setFoo(). Desde alguna otra clase, realice la llamada a ServiceLoader para obtener una instancia de Foo e inyéctela en el código que la necesita. Si luego se mueve a OSGi, simplemente elimine la segunda clase y use los Servicios Declarativos o Blueprint para manejar la inyección de los Servicios OSGi. –