This is a follow up to the threads:
[RT] IoC Type Who Cares?
[proposal] IoC type 3.14 extension to the Avalon Framework
If you are coming into this discussion late in the game, you may want to review the
above threads for more detail.
The Avalon Framework is a component framework that defines a conversation that can
take place between a component and its container. Its definition of a container is
currently very loose, which is ideal. However, there are advantages to defining an
optional container framework. Take PicoContainer for example; Pico's "type 3"
components may operate (conceptually) in many different containers, and PicoContainer
can be extended/implemented/mix-n-matched to come up with a wide variety of containers
that can run type-1, type-2, or type-3 components. It is very flexible, and the Pico
folks have come up with a lot of great ideas. However, the framework (Pico's), in my
opinion, has some short-comings. In addition, many developers will want to work with
a "pure Avalon" solution or a framework that is more tightly bound to the Avalon way
of doing things. It it my proposal that we give them one.
public interface RoleResolvableServiceManager
extends ServiceManager {
/* BEGIN from ServiceManager **
boolean hasService(String role);
Object lookup(String role)
throws ServiceException;
void release(Object service);
** END from ServiceManager */
String resolveRole(Class serviceInterface)
throws ServiceResolutionException;
}
public interface ServiceConstructor {
String getServiceRole();
Class getServiceInterface();
Object newService(RoleResolvableServiceManager serviceManager,
Context context)
throws ServiceResolutionException,
ServiceInstantiationException;
void verify(RoleResolvableServiceManager serviceManager)
throws ServiceResolutionException;
}
public interface ServiceContainer
extends ServiceManager, Disposable {
String ROLE = ServiceContainer.class.getName();
ServiceConstructor getConstructor(String role);
void registerService(ServiceConstructor sc)
throws ServiceRegistrationException;
void unregisterService(String role);
/* BEGIN from ServiceManager **
boolean hasService(String role);
Object lookup(String role)
throws ServiceException;
void release(Object service);
** END from ServiceManager */
Collection getServices();
Set getServiceRoles();
// Uncertain about this method...
// The List can be modifiable/unmodifiable
List getChildContainers();
void verify()
throws ServiceResolutionException;
// from Disposable
void dispose();
}
Now, I AM NOT advocating the above framework carte-blanche. It is a brainstorm. What
I AM advocating is simply the existence of a container framework. But since I am
brainstorming, I will attempt to give a walk-through.
The two crucial pieces of this puzzle are ServiceConstructor and ServiceContainer.
These are intended to be as loosely coupled as possible. My goal was that
ServiceConstructor(s) could be plugged in to ServiceContainer implementations,
regardless of the vendor.
A ServiceContainer is an abstraction that defines the ability to register a service,
to lookup a service (it extends ServiceManager), to list all available services within
the container, and to verify all dependencies within the container. I borrowed
heavily from PicoContainer, but I believe that my design is more straightforward and
more easily implemented. And while I do like the idea of
PicoContainer.getComponentMulticaster*, I don't think it belongs within the container
interface itself. A better idea (IMHO), would be something like:
multicasterFactory.createServiceMulticaster(container);
As you may notice in ServiceContainer, I have stuck with the notion of Avalon roles.
This complicates things slightly when using IoC type 3. These roles need to be able
to be mapped with their service interfaces. This is the reason for the
RoleResolvableServiceManager and resolveRole. A straightforward
RoleResolvableServiceManager.resolveRole implementation would be simply to attempt to
find the static field "ROLE" or to use the fully qualified interface name and then
invoke ServiceManager.hasService.
A ServiceConstructor is where the IoC type implementation is buried. It may support
type-1, type-3, type-3, or type-X components. A ServiceConstructor exposes the role
that a service is to fulfill. It also exposes the interface a service is to
implement, but it does not expose the implementation class itself. I feel that this
is more flexible. It provides a verify() method which can be used to check if the
given ServiceManager can resolve all of its dependencies. It also, quite naturally,
provides a newService() method which can be used by the ServiceContainer to
instantiate a registered service. The arguments provided to
newService(RoleResolvableServiceManager,Context) allow the constructor to resolve all
services (using ServiceManager) and/or container-dependent instruments (using Context).
The entire framework was designed primarily with ease-of-implementation in mind. A
straightforward ServiceContainer implementation would extend
RoleResolvableServiceManager and pass along itself into the ServiceConstructor
methods. A more security conscious implementation might differ.
Any questions, comments, criticisms?
Thanks!
Jonathan Hawkes