A way to opt out of access restrictions on non-exported members.
Peter Levart
peter.levart at gmail.com
Wed Nov 18 08:03:32 UTC 2015
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
More information about the jigsaw-dev
mailing list