Aplicación Java extensible con la clase ServiceLoader

Publicado por pico.dev el .
blog-stack java planeta-codigo programacion
Comentarios

Java ofrece un mecanismo incluido en el propio JDK para hacer las aplicaciones extensibles o ampliables en un momento posterior al de desarrollo. La clase ServiceLoader permite obtener las implementaciones definidas en el classpath de una determinada interfaz. En este artículo explico esta clase y muestro un ejemplo sencillo de como usarla.

Java

Puede que al desarrollar una aplicación necesitamos que esta sea extensible, esto significa que en el momento de desarrollo no conocemos las implementaciones de un determinado servicio que se proporcionarán en un futuro. Un servicio no es más que la implementación de una determinada interfaz que definimos en el momento de desarrollo. Java con la clase ServiceLoader proporciona un mecanismo estándar e incorporado en el JDK para cargar servicios con alguna propiedad interesante.

A través de la clase ServiceLoader y con su método estático load cargamos los servicios que implementen una determinada interfaz, en el parámetro de tipo Class indicamos la interfaz del servicio. Por ejemplo, supongamos que tenemos la siguiente definición de servicio:

En el momento de desarrollar esta aplicación podemos definir unos cuantos servicios que implementen la interfaz Saludador pero deseamos que en futuro podamos o un tercero pueda añadir más servicios para otros locales. La implementación de estos servicios en Español, Inglés y Euskera sería:

Iniciando la aplicación podemos obtener los servicios disponibles para ser usados con el siguiente código:

Para obtener el mensaje de saludo en el idioma que deseemos basta con obtenerlo de la lista si está disponible y usarlo:

La clase ServiceLoader busca los servicios en los archivos META-INF/services/[interfaz] que haya disponibles en cualquiera de las librerías jar incluidas en el classpath, en el caso de este ejemplo el archivo sería META-INF/services/io.github.picodotdev.serviceloader.Saludador y este su contenido con las tres implementaciones de servicios incluidas en el ejemplo:

La salida para el programa Main1.java y Main2.java respectivamente es:

Esta es una forma interesante de hacer extensible o ampliable una aplicación en un futuro. Destacar que simplemente incluyendo en el classpath una librería que incluya en el directorio META-INF/services un archivo con el nombre de la interfaz con su nombre cualificado, io.github.picodotdev.serviceloader.Saludador, las nuevas implementaciones de servicios se devolverán usando el método Service.load(Saludador.class) que se encargará de buscar los archivos en las librerías jar que los tengan.

Este mecanismo es que el se usa para permitir definir nuevos proveedores de ratios entre divisas en la librería de referencia Java Money (JSR-354) que proporciona una API para el trabajo con importes monetarios, ratios y divisas en Java. En otro artículo mostraré cómo definir un nuevo proveedor de ratios en esta API de Java Money.

El código fuente completo del ejemplo está en uno de mis repositorios de GitHub.

Referencia: