Skip to content

Commit 2ca3cf5

Browse files
committed
ServiceHelper: allow multiple service loadings
For each class in its provided Service list, the ServiceHelper will now scan its class pool looking for implementations. This should allow consuming software to do things like create a single top-level service that all plugin services extend. By creating a Context with the top-level service specified, all concrete implementations of the service subclasses will be loaded.
1 parent ccabacf commit 2ca3cf5

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

src/main/java/org/scijava/service/ServiceHelper.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,35 @@ public ServiceHelper(final Context context,
121121
/**
122122
* Ensures all candidate service classes are registered in the index, locating
123123
* and instantiating compatible services as needed.
124+
* <p>
125+
* This is a NxM operation, where N is the number of service classes attached
126+
* to this ServiceHelper, and M is the number of discovered plugins. Multiple
127+
* implementations of a given service subclass can be loaded. For example, if
128+
* FooService, a subclass of {@link Service} (whether abstract, concrete, or
129+
* an interface), appears on the service list, all subclasses of FooService in
130+
* the plugin class pool will be loaded.
131+
* </p>
132+
* <p>
133+
* NB: In typical use, a {@link Context} will only return the highest priority
134+
* implementation for a loaded service. To retrieve the lower priority
135+
* service(s), they must be requested directly (or through a superclass not
136+
* shared with the higher priority implementation). Thus, as these lower
137+
* priority services will go unused in many cases, it is critical that service
138+
* loading (initialization) is as lightweight as possible.
139+
* </p>
124140
*
125141
* @throws IllegalArgumentException if one of the requested services is
126142
* required (i.e., not marked {@link Optional}) but cannot be
127143
* filled.
128144
*/
129145
public void loadServices() {
130146
for (final Class<? extends Service> serviceClass : serviceClasses) {
147+
// Load all compatible classes
148+
for (Class<? extends Service> c : classPoolList) {
149+
if (serviceClass.isAssignableFrom(c)) loadService(c);
150+
}
151+
152+
// Make sure loadService gets called once on the actual provided class
131153
loadService(serviceClass);
132154

133155
if (LogService.class.isAssignableFrom(serviceClass)) {

0 commit comments

Comments
 (0)