The other day I came across some inconvenience using java.util.ServiceLoader , and some questions formed in me.
Suppose I have a shared service:
public interface Service<T> { ... }
I could not explicitly tell ServiceLoader to load only implementations with a specific generic type.
ServiceLoader<Service<String>> services = ServiceLoader.load(Service.class); // Fail.
My question is: what are reasonable ways to use ServiceLoader to securely load shared service implementations?
After you asked the above question and before Paŭlo answered, I managed to find a solution.
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!"); }
Changing boolean canServe(Class<?> t) to boolean canServe(Object o) , as well as changing <T> Service<T> getService(Class<?> t) in the same way can be more dynamic (I use the latter for myself, since at the beginning I had the boolean canHandle(T t) method on my interface.)
java java-6
Kohányi Róbert
source share