Java Language Exemple simple de ServiceLoader


Exemple

Le ServiceLoader est un mécanisme intégré simple et facile à utiliser pour le chargement dynamique des implémentations d'interface. Avec le chargeur de service - fournissant des moyens pour l’instauration (mais pas le câblage) - un simple mécanisme d’injection de dépendance peut être intégré à Java SE. Avec l’interface ServiceLoader, la séparation de l’implémentation devient naturelle et les programmes peuvent être facilement étendus. En fait, de nombreuses API Java sont implémentées sur la base du ServiceLoader

Les concepts de base sont

  • Fonctionnant sur des interfaces de services
  • Obtention des implémentations du service via ServiceLoader
  • Mise en place de services

Commençons par l'interface et placez-la dans un pot nommé par exemple accounting-api.jar

package example;

public interface AccountingService {

  long getBalance();
}

Maintenant, nous fournissons une implémentation de ce service dans un jar nommé accounting-impl.jar , contenant une implémentation du service

package example.impl;
import example.AccountingService;

public interface DefaultAccountingService implements AccouningService {

  public long getBalance() {
    return balanceFromDB();
  }

  private long balanceFromDB(){
    ...
  }
}

De plus, le fichier accounting-impl.jar contient un fichier déclarant que ce fichier jar fournit une implémentation de AccountingService . Le fichier doit avoir un chemin commençant par META-INF/services/ et doit avoir le même nom que le nom complet de l'interface:

  • META-INF/services/example.AccountingService

Le contenu du fichier est le nom entièrement qualifié de l'implémentation:

example.impl.DefaultAccountingService

Étant donné que les deux jars se trouvent dans le chemin de classe du programme, qui utilise AccountingService , une instance du service peut être obtenue à l'aide de ServiceLauncher.

ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
AccountingService service = loader.next();
long balance = service.getBalance();

Comme ServiceLoader est une Iterable , il prend en charge plusieurs fournisseurs d’implémentation, parmi lesquels le programme peut choisir:

ServiceLoader<AccountingService> loader = ServiceLoader.load(AccountingService.class)
for(AccountingService service : loader) {
   //...
}

Notez que lors de l'appel de next() une nouvelle instance sera toujours créée. Si vous souhaitez réutiliser une instance, vous devez utiliser la méthode iterator() du ServiceLoader ou la boucle for-each, comme indiqué ci-dessus.