Customizing Service Qualifiers
Sometimes an injector contains multiple instances of a component that are published using the same type.
(For details on how to customize service types see the "Customizing Service Types" document.)
In this scenario it is useful to distinguish different services of the same type but different semantics
using a "qualifier". Within Sting, a qualifier is an opaque, user-supplied string that is specified using
the @Named
annotation. The @Named
annotation can be added to
where a service is published or where a service is consumed.
The publishing locations include on a type annotated by the @Injectable
annotation or a provider method enclosed within a type annotated by the @Fragment
annotation. A service is consumed by being passed as; constructor parameters in injectable components or
as method parameters passed to provider methods. These parameters can also be annotated with the
@Named
annotation. When sting compiles the injector, it ensures that the consumer service
dependency can only be satisfied by services published by a producer component if they have the same qualifier.
Qualified Components
Consider an application that consists of many components that all publish the same service interface of type
SimulationSystem
but need to be connected in specific topologies. This is possible to implement using
the @Named
annotation.
The DynamicLightingSystem
publishes a service with the SimulationSystem
type and the qualifier
"system:lighting"
.
@Injectable
@Named( "system:lighting" )
@Typed( SimulationSystem.class )
public class DynamicLightingSystem
implements SimulationSystem
{
...
}
This could be consumed by another component defined in a provider method:
@Fragment
public interface SimulationFragment
{
@Named( "system:particleSystem" )
default SimulationSystem provideParticleSimulationSystem( @Named( "system:lighting" ) SimulationSystem lighting )
{
...
}
...
}
The component could also be consumed by other injectable components:
@Injectable
public class GeometryProcessor
{
GeometryProcessor( @Named( "system:particleSystem" ) SimulationSystem particleSystem,
@Named( "system:lighting" ) SimulationSystem lighting )
{
...
}
...
}
Qualified Values
While qualified components occasionally occur in applications, it is far more common to
see the @Named
annotation used when configuring the application with
multiple instances of primitive or immutable values. For instance a component could accept
multiple parameters of type string for different configuration settings. For example:
@Injectable
public class HttpClient
{
HttpClient( @Named( "cfg:hostname" ) String hostname,
@Named( "cfg:port" ) int port,
@Named( "cfg:connectTimeout" ) int connectTimeout,
@Named( "cfg:username" ) String username,
@Named( "cfg:password" ) String password )
{
...
}
...
}
Qualifier Format
The actual value of the qualifier string is relatively arbitrary and you should use whatever makes sense within your application. Some projects use reverse DNS naming to guarantee uniqueness, others use short prefixes for namespacing while other projects use short local names.