-
Notifications
You must be signed in to change notification settings - Fork 669
/
Copy pathServiceLoader.java
2188 lines (1923 loc) · 94.5 KB
/
ServiceLoader.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.ClassLoaders;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.VM;
import jdk.internal.module.ServicesCatalog;
import jdk.internal.module.ServicesCatalog.ServiceProvider;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
/**
* A facility to load implementations of a service.
*
* <p> A <i>service</i> is a well-known interface or class for which zero, one,
* or many service providers exist. A <i>service provider</i> (or just
* <i>provider</i>) is a class that implements or subclasses the well-known
* interface or class. A {@code ServiceLoader} is an object that locates and
* loads service providers deployed in the run time environment at a time of an
* application's choosing. Application code refers only to the service, not to
* service providers, and is assumed to be capable of differentiating between
* multiple service providers as well as handling the possibility that no service
* providers are located.
*
* <h3> Obtaining a service loader </h3>
*
* <p> An application obtains a service loader for a given service by invoking
* one of the static {@code load} methods of ServiceLoader. If the application
* is a module, then its module declaration must have a <i>uses</i> directive
* that specifies the service; this helps to locate providers and ensure they
* will execute reliably. In addition, if the service is not in the application
* module, then the module declaration must have a <i>requires</i> directive
* that specifies the module which exports the service.
*
* <p> A service loader can be used to locate and instantiate providers of the
* service by means of the {@link #iterator() iterator} method. {@code ServiceLoader}
* also defines the {@link #stream() stream} method to obtain a stream of providers
* that can be inspected and filtered without instantiating them.
*
* <p> As an example, suppose the service is {@code com.example.CodecFactory}, an
* interface that defines methods for producing encoders and decoders:
*
* <pre>{@code
* package com.example;
* public interface CodecFactory {
* Encoder getEncoder(String encodingName);
* Decoder getDecoder(String encodingName);
* }
* }</pre>
*
* <p> The following code obtains a service loader for the {@code CodecFactory}
* service, then uses its iterator (created automatically by the enhanced-for
* loop) to yield instances of the service providers that are located:
*
* <pre>{@code
* ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
* for (CodecFactory factory : loader) {
* Encoder enc = factory.getEncoder("PNG");
* if (enc != null)
* ... use enc to encode a PNG file
* break;
* }
* }</pre>
*
* <p> If this code resides in a module, then in order to refer to the
* {@code com.example.CodecFactory} interface, the module declaration would
* require the module which exports the interface. The module declaration would
* also specify use of {@code com.example.CodecFactory}:
* <pre>{@code
* requires com.example.codec.core;
* uses com.example.CodecFactory;
* }</pre>
*
* <p> Sometimes an application may wish to inspect a service provider before
* instantiating it, in order to determine if an instance of that service
* provider would be useful. For example, a service provider for {@code
* CodecFactory} that is capable of producing a "PNG" encoder may be annotated
* with {@code @PNG}. The following code uses service loader's {@code stream}
* method to yield instances of {@code Provider<CodecFactory>} in contrast to
* how the iterator yields instances of {@code CodecFactory}:
* <pre>{@code
* ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
* Set<CodecFactory> pngFactories = loader
* .stream() // Note a below
* .filter(p -> p.type().isAnnotationPresent(PNG.class)) // Note b
* .map(Provider::get) // Note c
* .collect(Collectors.toSet());
* }</pre>
* <ol type="a">
* <li> A stream of {@code Provider<CodecFactory>} objects </li>
* <li> {@code p.type()} yields a {@code Class<CodecFactory>} </li>
* <li> {@code get()} yields an instance of {@code CodecFactory} </li>
* </ol>
*
* <h3> Designing services </h3>
*
* <p> A service is a single type, usually an interface or abstract class. A
* concrete class can be used, but this is not recommended. The type may have
* any accessibility. The methods of a service are highly domain-specific, so
* this API specification cannot give concrete advice about their form or
* function. However, there are two general guidelines:
* <ol>
* <li><p> A service should declare as many methods as needed to allow service
* providers to communicate their domain-specific properties and other
* quality-of-implementation factors. An application which obtains a service
* loader for the service may then invoke these methods on each instance of
* a service provider, in order to choose the best provider for the
* application. </p></li>
* <li><p> A service should express whether its service providers are intended
* to be direct implementations of the service or to be an indirection
* mechanism such as a "proxy" or a "factory". Service providers tend to be
* indirection mechanisms when domain-specific objects are relatively
* expensive to instantiate; in this case, the service should be designed
* so that service providers are abstractions which create the "real"
* implementation on demand. For example, the {@code CodecFactory} service
* expresses through its name that its service providers are factories
* for codecs, rather than codecs themselves, because it may be expensive
* or complicated to produce certain codecs. </p></li>
* </ol>
*
* <h3> <a id="developing-service-providers">Developing service providers</a> </h3>
*
* <p> A service provider is a single type, usually a concrete class. An
* interface or abstract class is permitted because it may declare a static
* provider method, discussed later. The type must be public and must not be
* an inner class.
*
* <p> A service provider and its supporting code may be developed in a module,
* which is then deployed on the application module path or in a modular
* image. Alternatively, a service provider and its supporting code may be
* packaged as a JAR file and deployed on the application class path. The
* advantage of developing a service provider in a module is that the provider
* can be fully encapsulated to hide all details of its implementation.
*
* <p> An application that obtains a service loader for a given service is
* indifferent to whether providers of the service are deployed in modules or
* packaged as JAR files. The application instantiates service providers via
* the service loader's iterator, or via {@link Provider Provider} objects in
* the service loader's stream, without knowledge of the service providers'
* locations.
*
* <h3> Deploying service providers as modules </h3>
*
* <p> A service provider that is developed in a module must be specified in a
* <i>provides</i> directive in the module declaration. The provides directive
* specifies both the service and the service provider; this helps to locate the
* provider when another module, with a <i>uses</i> directive for the service,
* obtains a service loader for the service. It is strongly recommended that the
* module does not export the package containing the service provider. There is
* no support for a module specifying, in a <i>provides</i> directive, a service
* provider in another module.
*
* <p> A service provider that is developed in a module has no control over when
* it is instantiated, since that occurs at the behest of the application, but it
* does have control over how it is instantiated:
*
* <ul>
*
* <li> If the service provider declares a provider method, then the service
* loader invokes that method to obtain an instance of the service provider. A
* provider method is a public static method named "provider" with no formal
* parameters and a return type that is assignable to the service's interface
* or class.
* <p> In this case, the service provider itself need not be assignable to the
* service's interface or class. </li>
*
* <li> If the service provider does not declare a provider method, then the
* service provider is instantiated directly, via its provider constructor. A
* provider constructor is a public constructor with no formal parameters.
* <p> In this case, the service provider must be assignable to the service's
* interface or class </li>
*
* </ul>
*
* <p> A service provider that is deployed as an
* {@linkplain java.lang.module.ModuleDescriptor#isAutomatic automatic module} on
* the application module path must have a provider constructor. There is no
* support for a provider method in this case.
*
* <p> As an example, suppose a module specifies the following directives:
* <pre>{@code
* provides com.example.CodecFactory with com.example.impl.StandardCodecs;
* provides com.example.CodecFactory with com.example.impl.ExtendedCodecsFactory;
* }</pre>
*
* <p> where
*
* <ul>
* <li> {@code com.example.CodecFactory} is the two-method service from
* earlier. </li>
*
* <li> {@code com.example.impl.StandardCodecs} is a public class that implements
* {@code CodecFactory} and has a public no-args constructor. </li>
*
* <li> {@code com.example.impl.ExtendedCodecsFactory} is a public class that
* does not implement CodecFactory, but it declares a public static no-args
* method named "provider" with a return type of {@code CodecFactory}. </li>
* </ul>
*
* <p> A service loader will instantiate {@code StandardCodecs} via its
* constructor, and will instantiate {@code ExtendedCodecsFactory} by invoking
* its {@code provider} method. The requirement that the provider constructor or
* provider method is public helps to document the intent that the class (that is,
* the service provider) will be instantiated by an entity (that is, a service
* loader) which is outside the class's package.
*
* <h3> Deploying service providers on the class path </h3>
*
* A service provider that is packaged as a JAR file for the class path is
* identified by placing a <i>provider-configuration file</i> in the resource
* directory {@code META-INF/services}. The name of the provider-configuration
* file is the fully qualified binary name of the service. The provider-configuration
* file contains a list of fully qualified binary names of service providers, one
* per line.
*
* <p> For example, suppose the service provider
* {@code com.example.impl.StandardCodecs} is packaged in a JAR file for the
* class path. The JAR file will contain a provider-configuration file named:
*
* <blockquote>{@code
* META-INF/services/com.example.CodecFactory
* }</blockquote>
*
* that contains the line:
*
* <blockquote>{@code
* com.example.impl.StandardCodecs # Standard codecs
* }</blockquote>
*
* <p><a id="format">The provider-configuration file must be encoded in UTF-8. </a>
* Space and tab characters surrounding each service provider's name, as well as
* blank lines, are ignored. The comment character is {@code '#'}
* ({@code '\u0023'} <span style="font-size:smaller;">NUMBER SIGN</span>);
* on each line all characters following the first comment character are ignored.
* If a service provider class name is listed more than once in a
* provider-configuration file then the duplicate is ignored. If a service
* provider class is named in more than one configuration file then the duplicate
* is ignored.
*
* <p> A service provider that is mentioned in a provider-configuration file may
* be located in the same JAR file as the provider-configuration file or in a
* different JAR file. The service provider must be visible from the class loader
* that is initially queried to locate the provider-configuration file; this is
* not necessarily the class loader which ultimately locates the
* provider-configuration file.
*
* <h3> Timing of provider discovery </h3>
*
* <p> Service providers are loaded and instantiated lazily, that is, on demand.
* A service loader maintains a cache of the providers that have been loaded so
* far. Each invocation of the {@code iterator} method returns an {@code Iterator}
* that first yields all of the elements cached from previous iteration, in
* instantiation order, and then lazily locates and instantiates any remaining
* providers, adding each one to the cache in turn. Similarly, each invocation
* of the stream method returns a {@code Stream} that first processes all
* providers loaded by previous stream operations, in load order, and then lazily
* locates any remaining providers. Caches are cleared via the {@link #reload
* reload} method.
*
* <h3> <a id="errors">Errors</a> </h3>
*
* <p> When using the service loader's {@code iterator}, the {@link
* Iterator#hasNext() hasNext} and {@link Iterator#next() next} methods will
* fail with {@link ServiceConfigurationError} if an error occurs locating,
* loading or instantiating a service provider. When processing the service
* loader's stream then {@code ServiceConfigurationError} may be thrown by any
* method that causes a service provider to be located or loaded.
*
* <p> When loading or instantiating a service provider in a module, {@code
* ServiceConfigurationError} can be thrown for the following reasons:
*
* <ul>
*
* <li> The service provider cannot be loaded. </li>
*
* <li> The service provider does not declare a provider method, and either
* it is not assignable to the service's interface/class or does not have a
* provider constructor. </li>
*
* <li> The service provider declares a public static no-args method named
* "provider" with a return type that is not assignable to the service's
* interface or class. </li>
*
* <li> The service provider class file has more than one public static
* no-args method named "{@code provider}". </li>
*
* <li> The service provider declares a provider method and it fails by
* returning {@code null} or throwing an exception. </li>
*
* <li> The service provider does not declare a provider method, and its
* provider constructor fails by throwing an exception. </li>
*
* </ul>
*
* <p> When reading a provider-configuration file, or loading or instantiating
* a provider class named in a provider-configuration file, then {@code
* ServiceConfigurationError} can be thrown for the following reasons:
*
* <ul>
*
* <li> The format of the provider-configuration file violates the <a
* href="ServiceLoader.html#format">format</a> specified above; </li>
*
* <li> An {@link IOException IOException} occurs while reading the
* provider-configuration file; </li>
*
* <li> A service provider cannot be loaded; </li>
*
* <li> A service provider is not assignable to the service's interface or
* class, or does not define a provider constructor, or cannot be
* instantiated. </li>
*
* </ul>
*
* <h3> Security </h3>
*
* <p> Service loaders always execute in the security context of the caller
* of the iterator or stream methods and may also be restricted by the security
* context of the caller that created the service loader.
* Trusted system code should typically invoke the methods in this class, and
* the methods of the iterators which they return, from within a privileged
* security context.
*
* <h3> Concurrency </h3>
*
* <p> Instances of this class are not safe for use by multiple concurrent
* threads.
*
* <h3> Null handling </h3>
*
* <p> Unless otherwise specified, passing a {@code null} argument to any
* method in this class will cause a {@link NullPointerException} to be thrown.
*
* @param <S> The type of the service to be loaded by this loader
*
* @author Mark Reinhold
* @revised 9
* @spec JPMS
* @since 1.6
*/
/*
* 服务加载器,加载系统中已注册的指定类型的服务
*
* 在非模块化系统中,需要在项目根目录的/META-INF/services文件夹下放置注册文件
* 在模块化系统中,只需要在module-info中填写provides和use信息就可以了
*/
public final class ServiceLoader<S> implements Iterable<S> {
private static JavaLangAccess LANG_ACCESS; // java.lang包中的后门
// The class of the service type
private final String serviceName; // 当前服务加载器将要加载的服务名称(服务接口名称)
// The class or interface representing the service being loaded
private final Class<S> service; // 当前服务加载器将要加载的服务类型(服务接口)
// The module layer used to locate providers; null when locating providers using a class loader
private final ModuleLayer layer; // 用于定位服务提供者的layer,如果使用类加载器搜索,则此项可以设置为null
// The class loader used to locate, load, and instantiate providers; null when locating provider using a module layer
private final ClassLoader loader; // 用来加载服务接口的类加载器
private final List<S> instantiatedProviders = new ArrayList<>(); // 缓存已经加载过的服务提供者对象
// The lazy-lookup iterator for iterator operations
private Iterator<Provider<S>> lookupIterator1; // 服务查询器,用来查找服务提供者工厂,用在普通迭代操作中
// The lazy-lookup iterator for stream operations
private Iterator<Provider<S>> lookupIterator2; // 服务查询器,用来查找服务提供者工厂,用在流式操作中
private final List<Provider<S>> loadedProviders = new ArrayList<>(); // 在流式操作中缓存查找到的服务提供者工厂
// true when all providers loaded
private boolean loadedAllProviders; // 记录在流式操作中是否已加载所有服务提供者工厂
// Incremented when reload is called
private int reloadCount; // 记录服务加载器的重置次数
// The access control context taken when the ServiceLoader is created
private final AccessControlContext acc;
static {
LANG_ACCESS = SharedSecrets.getJavaLangAccess();
}
/*▼ 构造方法 ████████████████████████████████████████████████████████████████████████████████┓ */
/**
* Initializes a new instance of this class for locating service providers
* in a module layer.
*
* @throws ServiceConfigurationError If {@code svc} is not accessible to {@code caller} or the caller
* module does not use the service type.
*/
private ServiceLoader(Class<?> caller, ModuleLayer layer, Class<S> service) {
Objects.requireNonNull(caller);
Objects.requireNonNull(layer);
Objects.requireNonNull(service);
// 确保服务的使用者caller可以使用服务service
checkCaller(caller, service);
this.service = service;
this.serviceName = service.getName();
this.layer = layer;
this.loader = null;
this.acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
}
/**
* Initializes a new instance of this class for locating service providers
* via a class loader.
*
* @throws ServiceConfigurationError If {@code svc} is not accessible to {@code caller} or the caller
* module does not use the service type.
*/
private ServiceLoader(Class<?> caller, Class<S> service, ClassLoader cl) {
Objects.requireNonNull(service);
// 虚拟机是否已经完成初始化
if(VM.isBooted()) {
// 确保服务的使用者caller可以使用服务service
checkCaller(caller, service);
if(cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
} else {
/*
* if we get here then it means that ServiceLoader is being used before the VM initialization has completed.
* At this point then only code in the java.base should be executing.
*/
// 虚拟机初始化期间只允许java.base中的代码执行
Module callerModule = caller.getModule();
Module base = Object.class.getModule();
Module svcModule = service.getModule();
if(callerModule != base || svcModule != base) {
fail(service, "not accessible to " + callerModule + " during VM init");
}
// restricted to boot loader during startup
cl = null;
}
this.service = service;
this.serviceName = service.getName();
this.layer = null;
this.loader = cl;
this.acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
}
/**
* Initializes a new instance of this class for locating service providers
* via a class loader.
*
* @throws ServiceConfigurationError If the caller module does not use the service type.
* @apiNote For use by ResourceBundle
*/
private ServiceLoader(Module callerModule, Class<S> service, ClassLoader cl) {
// callerModule需要对service服务声明uses权限
if(!callerModule.canUse(service)) {
fail(service, callerModule + " does not declare `uses`");
}
this.service = Objects.requireNonNull(service);
this.serviceName = service.getName();
this.layer = null;
this.loader = cl;
this.acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
}
/*▲ 构造方法 ████████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 加载服务 ████████████████████████████████████████████████████████████████████████████████┓ */
/**
* Creates a new service loader for the given service type, using the
* current thread's {@linkplain java.lang.Thread#getContextClassLoader
* context class loader}.
*
* <p> An invocation of this convenience method of the form
* <pre>{@code
* ServiceLoader.load(service)
* }</pre>
*
* is equivalent to
*
* <pre>{@code
* ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
* }</pre>
*
* @param <S> the class of the service type
* @param service The interface or abstract class representing the service
*
* @return A new service loader
*
* @throws ServiceConfigurationError if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
* @apiNote Service loader objects obtained with this method should not be
* cached VM-wide. For example, different applications in the same VM may
* have different thread context class loaders. A lookup by one application
* may locate a service provider that is only visible via its thread
* context class loader and so is not suitable to be located by the other
* application. Memory leaks can also arise. A thread local may be suited
* to some applications.
* @revised 9
* @spec JPMS
*/
// 使用当前线程上下文类加载器加载指定的服务
@CallerSensitive
public static <S> ServiceLoader<S> load(Class<S> service) {
// 获取当前线程上下文类加载器
ClassLoader cl = Thread.currentThread().getContextClassLoader();
// 获取load()的调用者所在的类
Class<?> caller = Reflection.getCallerClass();
return new ServiceLoader<>(caller, service, cl);
}
/**
* Creates a new service loader for the given service. The service loader
* uses the given class loader as the starting point to locate service
* providers for the service. The service loader's {@link #iterator()
* iterator} and {@link #stream() stream} locate providers in both named
* and unnamed modules, as follows:
*
* <ul>
* <li> <p> Step 1: Locate providers in named modules. </p>
*
* <p> Service providers are located in all named modules of the class
* loader or to any class loader reachable via parent delegation. </p>
*
* <p> In addition, if the class loader is not the bootstrap or {@linkplain
* ClassLoader#getPlatformClassLoader() platform class loader}, then service
* providers may be located in the named modules of other class loaders.
* Specifically, if the class loader, or any class loader reachable via
* parent delegation, has a module in a {@linkplain ModuleLayer module
* layer}, then service providers in all modules in the module layer are
* located. </p>
*
* <p> For example, suppose there is a module layer where each module is
* in its own class loader (see {@link ModuleLayer#defineModulesWithManyLoaders
* defineModulesWithManyLoaders}). If this {@code ServiceLoader.load} method
* is invoked to locate providers using any of the class loaders created for
* the module layer, then it will locate all of the providers in the module
* layer, irrespective of their defining class loader. </p>
*
* <p> Ordering: The service loader will first locate any service providers
* in modules defined to the class loader, then its parent class loader,
* its parent parent, and so on to the bootstrap class loader. If a class
* loader has modules in a module layer then all providers in that module
* layer are located (irrespective of their class loader) before the
* providers in the parent class loader are located. The ordering of
* modules in same class loader, or the ordering of modules in a module
* layer, is not defined. </p>
*
* <p> If a module declares more than one provider then the providers
* are located in the order that its module descriptor {@linkplain
* java.lang.module.ModuleDescriptor.Provides#providers() lists the
* providers}. Providers added dynamically by instrumentation agents (see
* {@link java.lang.instrument.Instrumentation#redefineModule redefineModule})
* are always located after providers declared by the module. </p> </li>
*
* <li> <p> Step 2: Locate providers in unnamed modules. </p>
*
* <p> Service providers in unnamed modules are located if their class names
* are listed in provider-configuration files located by the class loader's
* {@link ClassLoader#getResources(String) getResources} method. </p>
*
* <p> The ordering is based on the order that the class loader's {@code
* getResources} method finds the service configuration files and within
* that, the order that the class names are listed in the file. </p>
*
* <p> In a provider-configuration file, any mention of a service provider
* that is deployed in a named module is ignored. This is to avoid
* duplicates that would otherwise arise when a named module has both a
* <i>provides</i> directive and a provider-configuration file that mention
* the same service provider. </p>
*
* <p> The provider class must be visible to the class loader. </p> </li>
*
* </ul>
*
* @param <S> the class of the service type
* @param service The interface or abstract class representing the service
* @param loader The class loader to be used to load provider-configuration files
* and provider classes, or {@code null} if the system class
* loader (or, failing that, the bootstrap class loader) is to be
* used
*
* @return A new service loader
*
* @throws ServiceConfigurationError if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
* @apiNote If the class path of the class loader includes remote network
* URLs then those URLs may be dereferenced in the process of searching for
* provider-configuration files.
*
* <p> This activity is normal, although it may cause puzzling entries to be
* created in web-server logs. If a web server is not configured correctly,
* however, then this activity may cause the provider-loading algorithm to fail
* spuriously.
*
* <p> A web server should return an HTTP 404 (Not Found) response when a
* requested resource does not exist. Sometimes, however, web servers are
* erroneously configured to return an HTTP 200 (OK) response along with a
* helpful HTML error page in such cases. This will cause a {@link
* ServiceConfigurationError} to be thrown when this class attempts to parse
* the HTML page as a provider-configuration file. The best solution to this
* problem is to fix the misconfigured web server to return the correct
* response code (HTTP 404) along with the HTML error page.
* @revised 9
* @spec JPMS
*/
// 使用指定的类加载器加载指定的服务
@CallerSensitive
public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader) {
// 获取load()的调用者所在的类
Class<?> caller = Reflection.getCallerClass();
return new ServiceLoader<>(caller, service, loader);
}
/**
* Creates a new service loader for the given service type to load service
* providers from modules in the given module layer and its ancestors. It
* does not locate providers in unnamed modules. The ordering that the service
* loader's {@link #iterator() iterator} and {@link #stream() stream} locate
* providers and yield elements is as follows:
*
* <ul>
* <li><p> Providers are located in a module layer before locating providers
* in parent layers. Traversal of parent layers is depth-first with each
* layer visited at most once. For example, suppose L0 is the boot layer, L1
* and L2 are modules layers with L0 as their parent. Now suppose that L3 is
* created with L1 and L2 as the parents (in that order). Using a service
* loader to locate providers with L3 as the context will locate providers
* in the following order: L3, L1, L0, L2. </p></li>
*
* <li><p> If a module declares more than one provider then the providers
* are located in the order that its module descriptor
* {@linkplain java.lang.module.ModuleDescriptor.Provides#providers()
* lists the providers}. Providers added dynamically by instrumentation
* agents are always located after providers declared by the module. </p></li>
*
* <li><p> The ordering of modules in a module layer is not defined. </p></li>
* </ul>
*
* @param <S> the class of the service type
* @param layer The module layer
* @param service The interface or abstract class representing the service
*
* @return A new service loader
*
* @throws ServiceConfigurationError if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
* @apiNote Unlike the other load methods defined here, the service type
* is the second parameter. The reason for this is to avoid source
* compatibility issues for code that uses {@code load(S, null)}.
* @spec JPMS
* @since 9
*/
// 在模块层layer中加载指定的服务;service是表示服务的接口或抽象类
@CallerSensitive
public static <S> ServiceLoader<S> load(ModuleLayer layer, Class<S> service) {
// 获取load()的调用者所在的类
Class<?> caller = Reflection.getCallerClass();
return new ServiceLoader<>(caller, layer, service);
}
/**
* Creates a new service loader for the given service type, using the
* {@linkplain ClassLoader#getPlatformClassLoader() platform class loader}.
*
* <p> This convenience method is equivalent to: </p>
*
* <pre>{@code
* ServiceLoader.load(service, ClassLoader.getPlatformClassLoader())
* }</pre>
*
* <p> This method is intended for use when only installed providers are
* desired. The resulting service will only find and load providers that
* have been installed into the current Java virtual machine; providers on
* the application's module path or class path will be ignored.
*
* @param <S> the class of the service type
* @param service The interface or abstract class representing the service
*
* @return A new service loader
*
* @throws ServiceConfigurationError if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
* @revised 9
* @spec JPMS
*/
// 使用platform类加载器加载已安装的服务,通常是扩展服务,不包括类路径和用户在应用中定义的服务
@CallerSensitive
public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
// 获取platform类加载器
ClassLoader cl = ClassLoader.getPlatformClassLoader();
// 获取load()的调用者所在的类
Class<?> caller = Reflection.getCallerClass();
return new ServiceLoader<>(caller, service, cl);
}
/**
* Creates a new service loader for the given service type, class
* loader, and caller.
*
* @param <S> the class of the service type
* @param service The interface or abstract class representing the service
* @param loader The class loader to be used to load provider-configuration files
* and provider classes, or {@code null} if the system class
* loader (or, failing that, the bootstrap class loader) is to be
* used
* @param callerModule The caller's module for which a new service loader is created
*
* @return A new service loader
*/
// 在callerModule模块中使用loader类加载器加载服务
static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader, Module callerModule) {
return new ServiceLoader<>(callerModule, service, loader);
}
/*▲ 加载服务 ████████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 获取服务 ████████████████████████████████████████████████████████████████████████████████┓ */
/**
* Returns an iterator to lazily load and instantiate the available
* providers of this loader's service.
*
* <p> To achieve laziness the actual work of locating and instantiating
* providers is done by the iterator itself. Its {@link Iterator#hasNext
* hasNext} and {@link Iterator#next next} methods can therefore throw a
* {@link ServiceConfigurationError} for any of the reasons specified in
* the <a href="#errors">Errors</a> section above. To write robust code it
* is only necessary to catch {@code ServiceConfigurationError} when using
* the iterator. If an error is thrown then subsequent invocations of the
* iterator will make a best effort to locate and instantiate the next
* available provider, but in general such recovery cannot be guaranteed.
*
* <p> Caching: The iterator returned by this method first yields all of
* the elements of the provider cache, in the order that they were loaded.
* It then lazily loads and instantiates any remaining service providers,
* adding each one to the cache in turn. If this loader's provider caches are
* cleared by invoking the {@link #reload() reload} method then existing
* iterators for this service loader should be discarded.
* The {@code hasNext} and {@code next} methods of the iterator throw {@link
* java.util.ConcurrentModificationException ConcurrentModificationException}
* if used after the provider cache has been cleared.
*
* <p> The iterator returned by this method does not support removal.
* Invoking its {@link java.util.Iterator#remove() remove} method will
* cause an {@link UnsupportedOperationException} to be thrown.
*
* @return An iterator that lazily loads providers for this loader's
* service
*
* @apiNote Throwing an error in these cases may seem extreme. The rationale
* for this behavior is that a malformed provider-configuration file, like a
* malformed class file, indicates a serious problem with the way the Java
* virtual machine is configured or is being used. As such it is preferable
* to throw an error rather than try to recover or, even worse, fail silently.
* @revised 9
* @spec JPMS
*/
// 返回服务提供者迭代器
public Iterator<S> iterator() {
// create lookup iterator if needed
if(lookupIterator1 == null) {
// 获取服务查询器,通过该查询器可以查找所有注册的服务提供者的服务提供者工厂
lookupIterator1 = newLookupIterator();
}
// 以迭代器形式返回服务提供者查询器,以便查询服务提供者
return new Iterator<S>() {
/* record reload count */
// 记录对服务目录缓存的清理次数
final int expectedReloadCount = ServiceLoader.this.reloadCount;
// index into the cached providers list
int index = 0;
// 是否存在下一个服务提供者(可能是潜在存在的,比如存在服务提供者工厂)
@Override
public boolean hasNext() {
// 确保服务查询器有效
checkReloadCount();
// 已遍历的服务索引 < 已实例化的服务索引
if(index<instantiatedProviders.size()) {
return true;
}
// 是否存在服务提供者工厂
return lookupIterator1.hasNext();
}
// 返回下一个服务提供者
@Override
public S next() {
// 确保服务查询器有效
checkReloadCount();
S next;
if(index<instantiatedProviders.size()) {
next = instantiatedProviders.get(index);
} else {
// 获取下一个服务提供者的服务提供者工厂
Provider<S> nextProvider = lookupIterator1.next();
// 创建服务提供者的实例
next = nextProvider.get();
// 对服务提供者进行缓存
instantiatedProviders.add(next);
}
// 统计已加载的服务提供者数量
index++;
return next;
}
/**
* Throws ConcurrentModificationException if the list of cached providers has been cleared by reload.
*/
// 防止出现同步问题,即在查找某个服务的过程中服务查询器被重置
private void checkReloadCount() {
if(ServiceLoader.this.reloadCount != expectedReloadCount) {
throw new ConcurrentModificationException();
}
}
};
}
/**
* Load the first available service provider of this loader's service. This
* convenience method is equivalent to invoking the {@link #iterator()
* iterator()} method and obtaining the first element. It therefore
* returns the first element from the provider cache if possible, it
* otherwise attempts to load and instantiate the first provider.
*
* <p> The following example loads the first available service provider. If
* no service providers are located then it uses a default implementation.
* <pre>{@code
* CodecFactory factory = ServiceLoader.load(CodecFactory.class)
* .findFirst()
* .orElse(DEFAULT_CODECSET_FACTORY);
* }</pre>
*
* @return The first service provider or empty {@code Optional} if no
* service providers are located
*
* @throws ServiceConfigurationError If a provider class cannot be loaded for any of the reasons
* specified in the <a href="#errors">Errors</a> section above.
* @spec JPMS
* @since 9
*/
// 获取第一个服务提供者
public Optional<S> findFirst() {
Iterator<S> iterator = iterator();
if(iterator.hasNext()) {
return Optional.of(iterator.next());
} else {
return Optional.empty();
}
}
/**
* Returns a stream to lazily load available providers of this loader's
* service. The stream elements are of type {@link Provider Provider}, the
* {@code Provider}'s {@link Provider#get() get} method must be invoked to
* get or instantiate the provider.
*
* <p> To achieve laziness the actual work of locating providers is done
* when processing the stream. If a service provider cannot be loaded for any
* of the reasons specified in the <a href="#errors">Errors</a> section
* above then {@link ServiceConfigurationError} is thrown by whatever method
* caused the service provider to be loaded. </p>
*
* <p> Caching: When processing the stream then providers that were previously
* loaded by stream operations are processed first, in load order. It then
* lazily loads any remaining service providers. If this loader's provider
* caches are cleared by invoking the {@link #reload() reload} method then
* existing streams for this service loader should be discarded. The returned
* stream's source {@link Spliterator spliterator} is <em>fail-fast</em> and
* will throw {@link ConcurrentModificationException} if the provider cache
* has been cleared. </p>
*
* <p> The following examples demonstrate usage. The first example creates
* a stream of {@code CodecFactory} objects, the second example is the same
* except that it sorts the providers by provider class name (and so locate
* all providers).
* <pre>{@code
* Stream<CodecFactory> providers = ServiceLoader.load(CodecFactory.class)
* .stream()
* .map(Provider::get);
*
* Stream<CodecFactory> providers = ServiceLoader.load(CodecFactory.class)
* .stream()
* .sorted(Comparator.comparing(p -> p.type().getName()))
* .map(Provider::get);
* }</pre>
*
* @return A stream that lazily loads providers for this loader's service
*
* @spec JPMS
* @since 9
*/
// 返回流化的服务提供者工厂
public Stream<Provider<S>> stream() {
// use cached providers as the source when all providers loaded
if(loadedAllProviders) {
// 获取在流式操作中缓存的服务提供者工厂
return loadedProviders.stream();
}
// create lookup iterator if needed
if(lookupIterator2 == null) {
// 获取服务查询器,通过该查询器可以查找所有注册的服务提供者的服务提供者工厂
lookupIterator2 = newLookupIterator();
}
/* use lookup iterator and cached providers as source */
// 构造一个可分割迭代器,用来获取流中下一个服务提供者工厂
Spliterator<Provider<S>> spliterator = new ProviderSpliterator<>(lookupIterator2);
return StreamSupport.stream(spliterator, false);
}
/*▲ 获取服务 ████████████████████████████████████████████████████████████████████████████████┛ */
/**