Rozhranie poskytovateľa služieb Java

1. Prehľad

Java 6 predstavila funkciu na objavovanie a načítanie implementácií zodpovedajúcich danému rozhraniu: Service Provider Interface (SPI).

V tomto tutoriále si predstavíme komponenty Java SPI a ukážeme si, ako ich môžeme aplikovať na prípad praktického použitia.

2. Pojmy a definície Java SPI

Java SPI definuje štyri hlavné komponenty

2.1. Služby

Známa sada programovacích rozhraní a tried, ktoré poskytujú prístup k niektorým špecifickým funkciám alebo vlastnostiam aplikácie.

2.2. Rozhranie poskytovateľa služieb

Rozhranie alebo abstraktná trieda, ktorá slúži ako proxy alebo koncový bod služby.

Ak je službou jedno rozhranie, je to rovnaké ako rozhranie poskytovateľa služby.

Služba a SPI sú v prostredí Java Ecosystem dobre známe ako API.

2.3. Poskytovateľ služieb

Konkrétna implementácia SPI. Poskytovateľ služby obsahuje jednu alebo viac konkrétnych tried, ktoré implementujú alebo rozširujú typ služby.

Poskytovateľ služieb je konfigurovaný a identifikovaný prostredníctvom konfiguračného súboru poskytovateľa, ktorý sme vložili do adresára prostriedkov META-INF / služby. Názov súboru je úplný názov SPI a jeho obsah je úplný názov implementácie SPI.

Poskytovateľ služieb je nainštalovaný vo forme rozšírení, súboru jar, ktorý umiestnime do aplikačnej triedy, do triedy Java alebo do triedy definovanej používateľom.

2.4. ServiceLoader

V srdci SPI je ServiceLoader trieda. To má rolu lenivo objavovať a načítať implementácie. Využíva kontextovú cestu triedy na vyhľadanie implementácií poskytovateľa a na ich vloženie do internej medzipamäte.

3. Vzorky SPI v ekosystéme Java

Java poskytuje veľa SPI. Tu je niekoľko príkladov rozhrania poskytovateľa služieb a služieb, ktoré poskytuje:

  • Poskytovateľ meny: poskytuje lokalizované symboly mien pre Mena trieda.
  • Poskytovateľ miestneho názvu: poskytuje lokalizované názvy pre Miestne nastavenie trieda.
  • Poskytovateľ TimeZoneName: poskytuje lokalizované názvy časových pásiem pre Časové pásmo trieda.
  • DateFormatProvider: poskytuje formáty dátumu a času pre zadané miestne nastavenie.
  • NumberFormatProvider: poskytuje peňažné, celé a percentuálne hodnoty pre NumberFormat trieda.
  • Vodič: od verzie 4.0 podporuje rozhranie JDBC API vzor SPI. Staršie verzie používajú Class.forName () spôsob načítania ovládačov.
  • Poskytovateľ Persistence: poskytuje implementáciu API JPA.
  • JsonProvider: poskytuje objekty na spracovanie JSON.
  • JsonbProvider: poskytuje objekty väzby JSON.
  • Prípona: poskytuje rozšírenia pre kontajner CDI.
  • ConfigSourceProvider: poskytuje zdroj na načítanie vlastností konfigurácie.

4. Vitrína: Aplikácia výmenných kurzov mien

Teraz, keď chápeme základné informácie, poďme si popísať kroky, ktoré sú potrebné na nastavenie aplikácie výmenného kurzu.

Na zvýraznenie týchto krokov musíme použiť minimálne tri projekty: výmenný kurz-api, výmenný kurz-impl, a výmenný kurz-app.

V pododdiele 4.1. Sa budeme zaoberať Služby, SPI a ServiceLoadercez modul výmenný kurz-api, potom v pododdiele 4.2. implementujeme naše služby poskytovateľ v výmenný kurz-impl modulu a nakoniec všetko spojíme v pododdiele 4.3 prostredníctvom modulu výmenný kurz-app.

V skutočnosti môžeme poskytnúť toľko modulov, koľko potrebujeme pre service poskytovateľ a sprístupniť ich v triede modulu výmenný kurz-app.

4.1. Budovanie nášho API

Začneme vytvorením projektu Maven s názvom výmenný kurz-api. Je dobrým zvykom, že názov sa končí týmto výrazom api, ale môžeme to nazvať akokoľvek.

Potom vytvoríme modelovú triedu na vyjadrenie mien kurzov:

balík com.baeldung.rate.api; public class Quote {private String currency; súkromné ​​LocalDate dátum; ...}

A potom definujeme svoje Služby na načítanie ponúk vytvorením rozhrania QuoteManager:

balíček verejné rozhranie com.baeldung.rate.api QuoteManager {List getQuotes (String baseCurrency, LocalDate date); }

Ďalej vytvoríme SPI pre našu službu:

balíček com.baeldung.rate.spi; verejné rozhranie ExchangeRateProvider {QuoteManager create (); }

A nakoniec musíme vytvoriť triedu nástrojov ExchangeRate.java ktoré môžu byť použité kódom klienta. Táto trieda deleguje na ServiceLoader.

Najskôr vyvoláme statickú továrenskú metódu naložiť() získať inštanciu ServiceLoader:

ServiceLoader loader = ServiceLoader .load (ExchangeRateProvider.class); 

A potom vyvoláme iterovať () metóda na vyhľadanie a získanie všetkých dostupných implementácií.

Iterátor = loader.iterator (); 

Výsledok vyhľadávania je uložený v pamäti, aby sme mohli vyvolať ServiceLoader.reload () metóda na objavenie novo nainštalovaných implementácií:

Iterátor = loader.reload (); 

A tu je naša trieda užitočnosti:

verejná trieda ExchangeRate {ServiceLoader loader = ServiceLoader .load (ExchangeRateProvider.class); verejní poskytovatelia iterátora (boolean refresh) {if (refresh) {loader.reload (); } návrat loader.iterator (); }}

Teraz, keď máme službu na získanie všetkých nainštalovaných implementácií, môžeme ich všetky použiť v klientskom kóde na rozšírenie našej aplikácie alebo iba jednu výberom preferovanej implementácie.

Upozorňujeme, že táto trieda nástrojov nemusí byť súčasťou api projekt. Kód klienta sa môže rozhodnúť vyvolať Samotné metódy ServiceLoader.

4.2. Budovanie poskytovateľa služieb

Poďme teraz vytvoriť projekt Maven s názvom výmenný kurz-impl a do API pridáme závislosť API pom.xml:

 com.baeldung exchange-rate-api 1.0.0-SNAPSHOT 

Potom vytvoríme triedu, ktorá implementuje náš SPI:

public class YahooFinanceExchangeRateProvider implementuje ExchangeRateProvider {@Override public QuoteManager create () {return new YahooQuoteManagerImpl (); }}

A tu implementácia QuoteManager rozhranie:

verejná trieda YahooQuoteManagerImpl implementuje QuoteManager {@Override verejný zoznam getQuotes (reťazec baseCurrency, dátum LocalDate) {// načítanie z rozhrania Yahoo API}}

Aby sme boli odhalení, vytvoríme konfiguračný súbor poskytovateľa:

META-INF / services / com.baeldung.rate.spi.ExchangeRateProvider 

Obsahom súboru je úplný názov triedy implementácie SPI:

com.baeldung.rate.impl.YahooFinanceExchangeRateProvider 

4.3. Dať to dokopy

Na záver vytvoríme klientsky projekt s názvom výmenný kurz-app a pridajte závislý výmenný kurz-api do triedy:

 com.baeldung exchange-rate-api 1.0.0-SNAPSHOT 

V tomto okamihu môžeme zavolať SPI z našej aplikácie:

ExchangeRate.providers (). ForEach (poskytovateľ -> ...);

4.4. Spustenie aplikácie

Poďme sa teraz zamerať na zostavenie všetkých našich modulov:

mvn čistý balíček 

Potom spustíme našu aplikáciu s Java príkaz bez zohľadnenia poskytovateľa:

java -cp ./exchange-rate-api/target/exchange-rate-api-1.0.0-SNAPSHOT.jar:./exchange-rate-app/target/exchange-rate-app-1.0.0-SNAPSHOT.jar com.baeldung.rate.app.MainApp

Teraz zahrnieme nášho poskytovateľa do java.ext.dirs rozšírenie a aplikáciu znovu spustíme:

java -Djava.ext.dirs = $ JAVA_HOME / jre / lib / ext: ./ výmenný kurz-impl / cieľ: ./ výmenný kurz-impl / cieľ / záleží -cp ./exchange-rate-api/target/ výmenný kurz-api-1.0.0-SNAPSHOT.jar: ./ výmenný kurz-aplikácia / cieľ / výmenný kurz-aplikácia-1.0.0-SNAPSHOT.jar com.baeldung.rate.app.MainApp 

Vidíme, že náš poskytovateľ je načítaný.

5. Záver

Teraz, keď sme preskúmali mechanizmus Java SPI prostredníctvom dobre definovaných krokov, by malo byť jasné, ako používať Java SPI na vytvorenie ľahko rozšíriteľných alebo vymeniteľných modulov.

Aj keď náš príklad použil službu výmenného kurzu Yahoo na preukázanie sily pripojenia k iným existujúcim externým API, produkčné systémy sa pri vytváraní skvelých aplikácií SPI nemusia spoliehať na API tretích strán.

Kód, ako obvykle, nájdete na Githube.