This is the 7th day of my participation in the August Text Challenge.More challenges in August
Usage of ServiceLoader
The Java SE 6 platform provides a new API to help find, load, and consume service providers. In fact, the java.util.ServiceLoader class has been around since version 1.3 of the Java platform, but it only became a public API in Java SE 6.
1. What is
The ServiceLoader class is used to search for service providers in the application’s classPath (classPath) or in the runtime environment’s extended directory (java.ext.dirs). It loads these services and gives them to the program to use, and when new extensions are added, the ServiceLoader can find them and, knowing the interface, find and use various implementations of that interface.
2. How to use it
According to the official documentation, it is mainly used to load a series of service providers. In addition, the ServiceLoader can load the specified service Provider through the service Provider configuration file. After reading this paragraph, or more meng, start the example. We define two MessageService interfaces as follows:
public interface MessageService {
String getMessage(a);
}
Copy the code
RawMessage is implemented as follows:
package com.test.raw;
import com.test.service.MessageService;
public class RawMessage implements MessageService {
public String getMessage(a) {
return "Raw message"; }}Copy the code
FormattedMessage is implemented as follows:
package com.test.format;
import com.test.service.MessageService;
public class FormattedMessage implements MessageService {
public String getMessage(a) {
return "Formatted message"; }}Copy the code
Under the original code directory to create a meta-inf/services directory, and create a com. Test. Service. MessageService file. The filename must be the same as the full name of the MessageService class we defined earlier, which reads as follows:
com.test.raw.RawMessage
com.test.format.FormattedMessage
Copy the code
Load all services and use:
public class MessageConsumer {
public static void main(String[] args) {
ServiceLoader<MessageService> serviceLoader = ServiceLoader.load(MessageService.class);
for(MessageService service : serviceLoader) { System.out.println(service.getMessage()); }}}Copy the code
Running results:
Raw message
Formatted message
Copy the code
Does it look like a simple implementation of dependency injection? We can provide specific classes to the user through configuration files. Of course, there is a specific restriction for the ServiceLoader, which is that the implementation classes we provide must provide a no-argument constructor or the ServiceLoader will report an error.
Examples used in projects
try{ FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next(); . }catch (BundleException e) {
...
}
Copy the code
3. Some limitations
The ServiceLoader API is useful, but it has some limitations.
- You cannot inherit ServiceLoader, so you cannot modify its behavior.
You can use custom ClassLoader subclasses to change how classes are found, but you cannot extend the ServiceLoader itself.
- The current ServiceLoader class does not tell the application when a new provider is available at runtime. At the same time, you cannot add change listeners to the loader to find out if a new provider has been placed in an application-specific extension directory.