Sučelje davatelja Java usluga

1. Pregled

Java 6 predstavila je značajku za otkrivanje i učitavanje implementacija koje se podudaraju s danim sučeljem: Sučelje davatelja usluga (SPI).

U ovom uputstvu predstavit ćemo komponente Java SPI i pokazati kako ga možemo primijeniti na praktičnu primjenu.

2. Pojmovi i definicije Java SPI

Java SPI definira četiri glavne komponente

2.1. Servis

Poznati skup programskih sučelja i klasa koji pružaju pristup određenoj funkcionalnosti ili značajci aplikacije.

2.2. Sučelje davatelja usluga

Sučelje ili apstraktna klasa koja djeluje kao proxy ili krajnja točka usluge.

Ako je usluga jedno sučelje, to je isto kao sučelje davatelja usluga.

Usluga i SPI zajedno dobro su poznati u Java ekosustavu kao API.

2.3. Pružatelj usluga

Specifična primjena SPI-a. Davatelj usluga sadrži jednu ili više konkretnih klasa koje implementiraju ili proširuju vrstu usluge.

Davatelj usluga se konfigurira i identificira putem konfiguracijske datoteke davatelja koju stavljamo u direktorij resursa META-INF / usluge. Naziv datoteke potpuno je kvalificirani naziv SPI-a, a njegov sadržaj potpuno je kvalificirani naziv implementacije SPI-a.

Dobavljač usluga instaliran je u obliku ekstenzija, jar datoteke koju smještamo u stazu aplikacije, stazu Java nastavka ili u korisnički definiranu stazu.

2.4. ServiceLoader

U srcu SPI je ServiceLoader razred. Ovo ima ulogu lijenog otkrivanja i učitavanja implementacija. Koristi put staza konteksta za pronalaženje implementacija davatelja i njihovo stavljanje u internu predmemoriju.

3. SPI uzorci u Java ekosustavu

Java nudi mnoge SPI-je. Evo nekoliko primjera sučelja davatelja usluga i usluge koju pruža:

  • ValutaNameProvider: pruža lokalizirane simbole valuta za Valuta razred.
  • LocaleNameProvider: pruža lokalizirana imena za Lokalno razred.
  • TimeZoneNameProvider: pruža lokalizirana imena vremenskih zona za Vremenska zona razred.
  • DateFormatProvider: pruža formate datuma i vremena za određeni lokalitet.
  • NumberFormatProvider: daje novčane, cjelobrojne i postotne vrijednosti za Format broja razred.
  • Vozač: od verzije 4.0, JDBC API podržava obrazac SPI. Starije verzije koriste Class.forName () metoda za učitavanje upravljačkih programa.
  • Pružatelj trajnosti: osigurava implementaciju JPA API-ja.
  • JsonProvider: pruža JSON obradu objekata.
  • JsonbProvider: pruža JSON povezujuće objekte.
  • Proširenje: pruža proširenja za CDI spremnik.
  • ConfigSourceProvider: pruža izvor za dohvaćanje konfiguracijskih svojstava.

4. Izlog: aplikacija za devizne tečajeve

Sad kad razumijemo osnove, opišimo korake koji su potrebni za postavljanje aplikacije za tečaj.

Da bismo istaknuli ove korake, trebamo upotrijebiti najmanje tri projekta: tečaj-api, tečaj-impl, i tečajna-aplikacija.

U pododjeljku 4.1. Pokrivat ćemo Servis, SPI i ServiceLoaderkroz modul tečaj-api, zatim u potpoglavlju 4.2. implementirat ćemo naše servis davatelja usluga u tečaj-impl modul, i na kraju ćemo sve spojiti u pododjeljku 4.3 kroz modul tečajna-aplikacija.

U stvari, možemo pružiti onoliko modula koliko nam treba za service davatelja usluga i učiniti ih dostupnima na putu predavanja modula tečajna-aplikacija.

4.1. Izgradnja našeg API-ja

Počinjemo s izradom projekta Maven pod nazivom tečaj-api. Dobra je praksa da naziv završava s tim pojmom api, ali možemo ga nazvati kako god.

Zatim kreiramo klasu modela za predstavljanje tečaja valuta:

paket com.baeldung.rate.api; javna klasa Quote {private String currency; privatni datum LocalDate; ...}

I onda definiramo svoje Servis za pronalaženje citata stvaranjem sučelja QuoteManager:

paket com.baeldung.rate.api javno sučelje QuoteManager {Popis getQuotes (String baseCurrency, LocalDate datum); }

Dalje, kreiramo SPI za našu uslugu:

paket com.baeldung.rate.spi; javno sučelje ExchangeRateProvider {QuoteManager create (); }

I na kraju, moramo stvoriti klasu korisnosti ExchangeRate.java koji se može koristiti kodom klijenta. Ovaj razred delegira u ServiceLoader.

Prvo, pozivamo se na statičku tvorničku metodu opterećenje() da biste dobili instancu ServiceLoader:

Učitavač ServiceLoader = ServiceLoader .load (ExchangeRateProvider.class); 

A onda zazivamo ponoviti () metoda za pretraživanje i preuzimanje svih dostupnih implementacija.

Iterator = loader.iterator (); 

Rezultati pretraživanja su predmemorirani, tako da možemo pozvati ServiceLoader.reload () metoda kako bi se otkrile novoinstalirane implementacije:

Iterator = loader.reload (); 

I evo naše klase korisnosti:

javna klasa ExchangeRate {ServiceLoader loader = ServiceLoader .load (ExchangeRateProvider.class); davatelji javnih iteratora (logičko osvježavanje) {if (osvježavanje) {loader.reload (); } return loader.iterator (); }}

Sada kada imamo uslugu za dobivanje svih instaliranih implementacija, sve ih možemo koristiti u klijentskom kodu za proširenje naše aplikacije ili samo jednu odabirom željene implementacije.

Imajte na umu da ova klasa korisnosti ne mora biti dio api projekt. Klijentski kod može odabrati pozivanje Sama metoda ServiceLoader.

4.2. Izgradnja davatelja usluga

Stvorimo sada Maven projekt nazvan tečaj-impl i dodajemo ovisnost API-ja u pom.xml:

 com.baeldung tečaj-api 1.0.0-SNAPSHOT 

Zatim kreiramo klasu koja implementira naš SPI:

javna klasa YahooFinanceExchangeRateProvider implementira ExchangeRateProvider {@Override public QuoteManager create () {return new YahooQuoteManagerImpl (); }}

I ovdje provedba QuoteManager sučelje:

javna klasa YahooQuoteManagerImpl implementira QuoteManager {@Override javni popis getQuotes (String baseCurrency, LocalDate date) {// dohvaća iz Yahoo API-ja}}

Da bismo bili otkriveni, kreiramo konfiguracijsku datoteku davatelja usluga:

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

Sadržaj datoteke potpuno je kvalificirano ime klase implementacije SPI:

com.baeldung.rate.impl.YahooFinanceExchangeRateProvider 

4.3. Sastavljajući ga

Na kraju, kreirajmo klijentski projekt pod nazivom tečajna-aplikacija i dodajte putanju ovisnosti exchange-rate-api na put predavanja:

 com.baeldung tečaj-api 1.0.0-SNAPSHOT 

U ovom trenutku iz naše aplikacije možemo nazvati SPI:

ExchangeRate.providers (). ForEach (pružatelj -> ...);

4.4. Pokretanje aplikacije

Usredotočimo se sada na izgradnju svih naših modula:

mvn čist paket 

Zatim pokrećemo našu aplikaciju s Java naredba bez uzimanja u obzir davatelja usluge:

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

Sad ćemo uključiti našeg davatelja usluga u java.ext.dirs i ponovo pokrećemo aplikaciju:

java -Djava.ext.dirs = $ JAVA_HOME / jre / lib / ext: ./ exchange-rate-impl / target: ./ exchange-rate-impl / target / ovisi -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 

Vidimo da je naš davatelj usluga učitan.

5. Zaključak

Sad kad smo istražili mehanizam Java SPI kroz dobro definirane korake, trebalo bi biti jasno vidjeti kako koristiti Java SPI za stvaranje lako proširivih ili zamjenjivih modula.

Iako je naš primjer koristio Yahooovu uslugu deviznog tečaja da bi pokazao snagu priključenja na druge postojeće vanjske API-je, proizvodni se sustavi ne trebaju oslanjati na API-je treće strane za stvaranje izvrsnih SPI aplikacija.

Kôd se, kao i obično, može naći na Githubu.