On 11/16/2015 07:57 PM, Alan Bateman wrote:
On 16/11/2015 17:48, Neil Bartlett wrote:
Alan,
In your consideration does the following declaration break
encapsulation of a module, assuming that package “org.example.impl”
is not exported?
module foo {
provides org.example.api.ServiceInterface with
org.example.impl.ServiceImpl;
}
This appears to allow the ServiceLoader to punch through
encapsulation and obtain instances of a non-exported type.
Sure, but this just part of the support for services. In this example
then the service provider is fully encapsulated. The consumer of the
service can't access ServiceImpl, it instead accesses it via
ServiceInterface (assuming of course that the consumer reads the
module with ServiceInterface and org.example.api is exported to the
consumer).
How does this differ from a declaration that one might see in a
Dependency Injection framework such as Spring? I.e. something like:
<bean class=“org.example.impl.ServiceImpl”> …
There isn't way to give Spring super powers so this needs foo to
export org.example.impl to Spring.
-Alan.
Hi,
Just a thought (and I don't know yet if it is a good idea)...
ServiceLoader currently has the following method:
public static <S> ServiceLoader<S> load(Class<S> service,
ClassLoader loader)
With the following overload:
public static <S> ServiceLoader<S> load(Class<S> service,
ClassLoader loader, Function<Stream<Class<?>>, Stream<Class<?>>>
streamManipulator)
We (or Spring) could use it like:
ServiceLoader<ServiceInterface> loader = ServiceLoader.load(
ServiceInterface.class,
classLoader,
stream -> stream.filter(implClass ->
implClass.getName().equals("org.example.impl.ServiceImpl"))
);
This could also be used to code various other strategies for service
lookup, for example:
public @interface Order {
int value() default 100;
}
ServiceLoader<ServiceInterface> loader = ServiceLoader.load(
ServiceInterface.class,
classLoader,
stream -> stream.sorted(
comparing(implClass ->
implClass.getAnnotation(Order.class), comparing(Order::value))
)
);
This way the powers of instantiating the implementation classes are left
to ServiceLoader, but client can decide what implementation classes are
chosen.
Regards, Peter