He tropezado con algún inconveniente el otro día usando java.util.ServiceLoader
y algunas preguntas formadas en mí.Cargando implementaciones de servicios genéricos a través de java.util.ServiceLoader
Supongamos que tengo un servicio genérico:
public interface Service<T> { ... }
No podría decir de manera explícita ServiceLoader
para cargar sólo implementaciones con un tipo genérico específico.
ServiceLoader<Service<String>> services =
ServiceLoader.load(Service.class); // Fail.
Mi pregunta es: ¿cuáles son formas razonables para utilizar ServiceLoader
para cargar con seguridad puestas en práctica de un servicio genérico?
Después de hacer la pregunta anterior y antes de la respuesta de Paŭlo, he logrado encontrar una solución.
public interface Service<T> { ...
// true if an implementation can handle the given `t' type; false otherwise.
public boolean canHandle(Class<?> t) { ...
public final class StringService implements Service<String> { ...
@Override public boolean canHandle(Class<?> t) {
if (String.class.isAssignableFrom(type))
return true;
return false;
}
public final class DoubleService implements Service<Double> { ...
// ...
public final class Services { ...
public static <T> Service<T> getService(Class<?> t) {
for (Service<T> s : ServiceLoader.load(Service.class))
if (s.canServe(t))
return s;
throw new UnsupportedOperationException("No servings today my son!");
}
Cambio boolean canServe(Class<?> t)
-boolean canServe(Object o)
y también cambiando <T> Service<T> getService(Class<?> t)
de la misma manera puede ser más dinámico (estoy usando esta última para mí, ya que tenía un método boolean canHandle(T t)
en mi interfaz en el principio.)
Gracias! Su solución * podría * funcionar dados los detalles que he presentado. Sin embargo, no lo probé (todavía), porque se me ocurrió una solución * elegante * para el proyecto en el que estoy trabajando. He editado mi pregunta para presentar mi solución. Además, en una nota al margen: ¿sería demasiado complicado implementar algo como esto? 'META-INF/services/com.example.Service' donde el' com.example.El archivo Service' contendría algo como esto: ' = com.example.impl.StringService = com.example.impl.DoubleService' o algo más elaborado. –
No es demasiado complicado, pero tendrá que hacerlo usted mismo. (Sin embargo, use otro directorio para no entrar en conflicto con los archivos que utiliza 'ServiceLoader'). Una vez he vuelto a implementar el mecanismo 'ServiceLoader' para 1.5, pero luego descubro que otras partes de mi programa necesitan 1.6 de todos modos, entonces ' lo he tirado. –