@Retention(value=CLASS)
@Target(value={METHOD,FIELD})
public @interface ServiceDependency
For "add", "change", "remove" callbacks, the following method signatures are supported:
(Component comp, ServiceReference ref, Service service)
(Component comp, ServiceReference ref, Object service)
(Component comp, ServiceReference ref)
(Component comp, Service service)
(Component comp, Object service)
(Component comp)
(Component comp, Map properties, Service service)
(ServiceReference ref, Service service)
(ServiceReference ref, Object service)
(ServiceReference ref)
(Service service)
(Service service, Map properties)
(Map properties, Service, service)
(Service service, Dictionary properties)
(Dictionary properties, Service service)
(Object service)
(ServiceReference<T> service)
(ServiceObjects<T> service)
For "swap" callbacks, the following method signatures are supported:
(Service old, Service replace)
(Object old, Object replace)
(ServiceReference old, Service old, ServiceReference replace, Service replace)
(ServiceReference old, Object old, ServiceReference replace, Object replace)
(Component comp, Service old, Service replace)
(Component comp, Object old, Object replace)
(Component comp, ServiceReference old, Service old, ServiceReference replace, Service replace)
(Component comp, ServiceReference old, Object old, ServiceReference replace, Object replace)
(ServiceReference old, ServiceReference replace)
(Component comp, ServiceReference old, ServiceReference replace)
(ServiceObjects old, ServiceObjects replace)
(Component comp, ServiceObjects old, ServiceObjects replace)
When the dependency is injected on a class field, the following field types are supported:
The dependency can also be injected using a method callback:@Component class MyComponent { @ServiceDependency volatile MyDependency dependency; }
Same example as before, but the callback signatures includes service properties:@Component class MyComponent { @ServiceDependency void bind(MyDependency dependency) {} }
Another example, were we inject multiple dependencies to an Iterable field@Component class MyComponent { @ServiceDependency void bind(MyDependency dependency, Map<String, Object> serviceProperties) {} }
Another example, were we inject multiple dependencies to a Map field, allowing to inspect service dependency properties (the keys hold the services, and the values hold the associated service properties):@Component class MyComponent { @ServiceDependency final Iterable<Dependency> dependencies = new CopyOnWriteArrayList<>(); }
@Component class MyComponent { @ServiceDependency final Map<MyDependency, Dictionary<String, Object>> dependencies = new ConcurrentHashMap<>; }
Modifier and Type | Optional Element and Description |
---|---|
java.lang.String |
added
The callback method to be invoked when the service is available.
|
java.lang.String |
changed
The callback method to be invoked when the service properties have changed.
|
java.lang.Class<?> |
defaultImpl
Sets the default implementation for an
optional service dependency. |
java.lang.String |
filter
The Service dependency OSGi filter.
|
java.lang.String |
name
The name used when dynamically configuring this dependency from the init method.
|
boolean |
propagate
Returns true if the dependency service properties must be published along with the service.
|
java.lang.String |
removed
The callback method to invoke when the service is lost.
|
boolean |
required
Whether the Service dependency is required or not.
|
java.lang.Class<?> |
service
The type if the service this dependency is applying on.
|
java.lang.String |
swap
the method to call when the service was swapped due to addition or removal of an aspect
|
long |
timeout
The max time in millis to wait for the dependency availability.
|
public abstract java.lang.Class<?> service
ServiceDependency.Any
class. In this case, all services (matching the filter()
attribute if it is specified) will
be returned.public abstract java.lang.String filter
public abstract java.lang.Class<?> defaultImpl
optional
service dependency. You can use this to supply
your own implementation that will be used instead of a Null Object when the dependency is
not available. This is also convenient if the service dependency is not an interface
(which would cause the Null Object creation to fail) but a class.
Only use this attribute on an optional service dependency applied on a class field.public abstract boolean required
public abstract java.lang.String added
public abstract java.lang.String changed
public abstract java.lang.String removed
public abstract java.lang.String swap
public abstract long timeout
IllegalStateException
exception is raised (but the service is not deactivated).Notice that the changed/removed callbacks are not used when the timeout parameter is greater than -1. -1 means no timeout at all (default). 0 means that invocation on a missing service will fail immediately. A positive number represents the max timeout in millis to wait for the service availability. Sample Code:
@Component class MyServer implements Runnable { @ServiceDependency(timeout=15000) MyDependency dependency;. @Start void start() { (new Thread(this)).start(); } public void run() { try { dependency.doWork(); } catch (IllegalStateException e) { t.printStackTrace(); } }
public abstract java.lang.String name
filter
and required
flag from the Service's init method.
All unnamed dependencies will be injected before the init() method; so from the init() method, you can
then pick up whatever information needed from already injected (unnamed) dependencies, and configure dynamically
your named dependencies, which will then be calculated once the init() method returns.
See Init
annotation for an example usage of a dependency dynamically configured from the init method.
public abstract boolean propagate