0Pricing
Java Academy · Lekcja

Usługi z provides/uses

Rozdzielanie komponentów za pomocą service loadera

Usługi z provides/uses to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.

Rozdzielanie zależności za pomocą usług

Moduły mogą współpracować bez zależności od wzajemnych implementacji, korzystając ze wzorca ładowania usług.

Jeden moduł deklaruje, że uses interfejsu usługi, a inny deklaruje, że provides jego implementację. JVM łączy je ze sobą.

Trzy role

Usługa ma trzech uczestników:

  • Interfejs usługi: kontrakt znajdujący się w jednym z modułów
  • Dostawca: moduł dostarczający implementację
  • Konsument: moduł, który ładuje implementacje w czasie działania

Interfejs usługi

Najpierw należy zdefiniować kontrakt. Jest to zwykły interfejs w eksportowanym pakiecie, aby zarówno dostawcy, jak i konsumenci mogli się do niego odwoływać.

package com.example.spi;

public interface Codec {
    String name();
    byte[] encode(String input);
}

Konsument deklaruje uses

Moduł konsumenta deklaruje, że uses interfejsu. Informuje to JPMS, że moduł będzie wyszukiwać implementacje za pomocą ServiceLoader.

module com.example.app {
    requires com.example.spi;
    uses com.example.spi.Codec;
}

Dostawca deklaruje provides

Moduł dostawcy deklaruje, który interfejs implementuje, za pomocą provides ... with ..., podając nazwę swojej konkretnej klasy.

module com.example.base64 {
    requires com.example.spi;
    provides com.example.spi.Codec
        with com.example.base64.Base64Codec;
}

Implementacja dostawcy

Klasa implementacji jest zwykłą klasą Javy. Musi być publiczna i mieć albo publiczny konstruktor bezargumentowy, albo publiczną statyczną metodę provider().

package com.example.base64;

import com.example.spi.Codec;
import java.util.Base64;

public class Base64Codec implements Codec {
    public String name() { return "base64"; }
    public byte[] encode(String input) {
        return Base64.getEncoder().encode(input.getBytes());
    }
}

Ładowanie za pomocą ServiceLoader

W czasie działania konsument wywołuje ServiceLoader.load(Codec.class), aby uzyskać wszystkich dostępnych dostawców, a następnie iteruje po nich bez bezpośredniego połączenia z żadną implementacją na etapie kompilacji.

import com.example.spi.Codec;
import java.util.ServiceLoader;

public class App {
    public static void main(String[] args) {
        ServiceLoader<Codec> loader = ServiceLoader.load(Codec.class);
        for (Codec codec : loader) {
            System.out.println("Found codec: " + codec.name());
        }
    }
}

Dlaczego to jest tak potężne

Konsument nigdy nie odwołuje się do nazwy klasy dostawcy. Wystarczy umieścić nowy moduł dostawcy na ścieżce modułów, aby został automatycznie wykryty.

Umożliwia to tworzenie architektur wtyczek i przejrzyste odwracanie zależności.

Fabryka provider()

Jeśli tworzenie obiektu wymaga dodatkowej logiki, należy zamiast konstruktora bezargumentowego udostępnić publiczną statyczną metodę provider(). JPMS wywoła ją, aby uzyskać instancję.

package com.example.base64;

import com.example.spi.Codec;

public class CodecFactory {
    public static Codec provider() {
        return new Base64Codec();
    }
}

Wielu dostawców

Wiele modułów może dostarczać tę samą implementację interfejsu. ServiceLoader zwraca je wszystkie, dzięki czemu konsument może wybrać dostawcę według nazwy, priorytetu lub możliwości.

Dostawców można dodawać i usuwać bez modyfikowania kodu konsumenta.

Strumień dostawców

Od wersji Java 9 ServiceLoader udostępnia metodę stream(), która zwraca uchwyty Provider. Można je filtrować przed utworzeniem instancji, co jest przydatne, gdy tworzenie obiektów jest kosztowne.

import com.example.spi.Codec;
import java.util.ServiceLoader;

public class App {
    public static void main(String[] args) {
        Codec chosen = ServiceLoader.load(Codec.class).stream()
            .map(ServiceLoader.Provider::get)
            .filter(c -> c.name().equals("base64"))
            .findFirst()
            .orElseThrow();
        System.out.println("Using: " + chosen.name());
    }
}

Szybkie sprawdzenie

Proszę przypomnieć sobie, której dyrektywy używa każda z ról.

Podsumowanie

Poznali Państwo wzorzec usług modułowych:

  • Trzy role: interfejs usługi, dostawca i konsument
  • Konsument: uses; dostawca: provides ... with
  • Implementacje są ładowane w czasie działania za pomocą ServiceLoader
  • Dostawcy potrzebują publicznego konstruktora bezargumentowego lub statycznej metody provider()

Następnie: migracja istniejącego projektu do modułów.

Często zadawane pytania

Czy lekcja „Usługi z provides/uses” jest bezpłatna?

Tak — pełny tekst „Usługi z provides/uses” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Usługi z provides/uses”?

Rozdzielanie komponentów za pomocą service loadera Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Java Academy?

Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Usługi z provides/uses”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?

Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. module-info.java
  2. requires i exports
  3. Usługi z provides/uses
  4. Migracja do modułów
← Powrót do Java Academy