7
7
import io .avaje .lang .Nullable ;
8
8
import jakarta .inject .Provider ;
9
9
10
+ import java .io .*;
10
11
import java .lang .reflect .Type ;
12
+ import java .net .URL ;
11
13
import java .util .*;
12
14
import java .util .function .Consumer ;
13
15
import java .util .function .Supplier ;
16
+ import java .util .stream .Collectors ;
17
+ import java .util .stream .Stream ;
14
18
15
19
import static java .lang .System .Logger .Level .DEBUG ;
16
20
@@ -187,7 +191,7 @@ private void initClassLoader() {
187
191
188
192
private void initPropertyPlugin () {
189
193
propertyRequiresPlugin =
190
- ServiceLoader . load (PropertyRequiresPlugin .class , classLoader )
194
+ serviceLoad (PropertyRequiresPlugin .class )
191
195
.findFirst ()
192
196
.orElse (defaultPropertyPlugin ());
193
197
}
@@ -214,7 +218,7 @@ public BeanScope build() {
214
218
initPropertyPlugin ();
215
219
}
216
220
217
- ServiceLoader . load (Plugin .class , classLoader ).forEach (plugin -> plugin .apply (this ));
221
+ serviceLoad (Plugin .class ).forEach (plugin -> plugin .apply (this ));
218
222
// sort factories by dependsOn
219
223
FactoryOrder factoryOrder = new FactoryOrder (parent , includeModules , !suppliedBeans .isEmpty ());
220
224
if (factoryOrder .isEmpty ()) {
@@ -241,6 +245,32 @@ public BeanScope build() {
241
245
return builder .build (shutdownHook , start );
242
246
}
243
247
248
+ private <P > Stream <P > serviceLoad (Class <P > pluginClass ) {
249
+ return classLoader
250
+ .resources ("META-INF/services/" + pluginClass .getCanonicalName ())
251
+ .flatMap (this ::resourceLines )
252
+ .map (this ::serviceInstance );
253
+ }
254
+
255
+ @ SuppressWarnings ("unchecked" )
256
+ private <P > P serviceInstance (String className ) {
257
+ try {
258
+ final var clazz = classLoader .loadClass (className );
259
+ return (P ) clazz .getDeclaredConstructor ().newInstance ();
260
+ } catch (Throwable e ) {
261
+ throw new RuntimeException (e );
262
+ }
263
+ }
264
+
265
+ private Stream <String > resourceLines (URL url ) {
266
+ try (InputStream is = url .openStream ()) {
267
+ final var reader = new LineNumberReader (new InputStreamReader (is ));
268
+ return reader .lines ().collect (Collectors .toList ()).stream ();
269
+ } catch (IOException e ) {
270
+ throw new UncheckedIOException (e );
271
+ }
272
+ }
273
+
244
274
/**
245
275
* Return the type that we map the supplied bean to.
246
276
*/
0 commit comments