Úvod do Project Jigsaw

1. Úvod

Project Jigsaw je zastrešujúci projekt s novými funkciami zameranými na dva aspekty:

  • zavedenie modulového systému v jazyku Java
  • a jeho implementácia v zdroji JDK a prostredí Java runtime

V tomto článku vám predstavíme projekt Jigsaw a jeho vlastnosti a nakoniec ho zabalíme do jednoduchej modulárnej aplikácie.

2. Modularita

Jednoducho povedané, modularita je princíp návrhu, ktorý nám pomáha dosiahnuť:

  • voľné spojenie medzi komponentmi
  • jasné zmluvy a závislosti medzi komponentmi
  • skrytá implementácia pomocou silného zapuzdrenia

2.1. Jednotka modularity

Teraz nastáva otázka, čo je to jednotka modulárnosti? Vo svete Java, najmä s OSGi, sa JAR považovali za jednotku modularity.

Skupiny JAR pomohli pri zoskupovaní súvisiacich komponentov, majú však určité obmedzenia:

  • výslovné zmluvy a závislosti medzi JAR
  • slabé zapuzdrenie prvkov v rámci JAR

2.2. JAR peklo

S JAR bol ďalší problém - peklo JAR. Výsledkom viacerých verzií JAR ležiacich na triednej ceste bolo ClassLoader načítanie prvej nájdenej triedy z JAR s veľmi neočakávanými výsledkami.

Ďalším problémom spojeným s JVM s použitím classpath bolo, že kompilácia aplikácie by bola úspešná, ale aplikácia zlyhala za behu programu ClassNotFoundException, kvôli chýbajúcim súborom JAR na ceste triedy za behu.

2.3. Nová jednotka modularity

So všetkými týmito obmedzeniami, keď tvorcovia jazyka Java používali JAR ako jednotku modularity, prišli s novým konštruktom v jazyku zvanom moduly. A s týmto je pre Javu naplánovaný úplne nový modulárny systém.

3. Projekt Skladačka

Primárne motivácie pre tento projekt sú:

  • vytvoriť modulový systém pre jazyk - implementované podľa JEP 261
  • aplikujte to na zdroj JDK - implementované v rámci JEP 201
  • modulovať JDKknižnice - implementované v rámci JEP 200
  • aktualizujte runtime tak, aby podporoval modularitu - implementované v rámci JEP 220
  • byť schopný vytvoriť menší runtime s podmnožinou modulov z JDK - implementované podľa JEP 282

Ďalšou dôležitou iniciatívou je zapuzdrenie interných rozhraní API v JDK, teda tých, ktorí spadajú pod slnko.* balíčky a ďalšie neštandardné API. Tieto API nemali byť nikdy určené na použitie verejnosťou a nikdy sa neplánovalo ich udržiavanie. Ale sila týchto API spôsobila, že ich vývojári v Jave využili pri vývoji rôznych knižníc, rámcov a nástrojov. Pre niekoľko interných rozhraní API boli poskytnuté náhrady a ďalšie boli presunuté do interných modulov.

4. Nové nástroje pre modularitu

  • jdeps - pomáha pri analýze kódovej základne pri identifikácii závislostí na rozhraniach JDK API a JAR tretích strán. Uvádza sa v ňom aj názov modulu, kde možno nájsť rozhranie JDK API. To uľahčuje modularizáciu kódovej základne
  • jdeprscan - pomáha pri analýze kódovej základne na použitie akýchkoľvek zastaraných rozhraní API
  • jlink - pomáha pri vytváraní menšieho modulu runtime kombináciou modulov aplikácie a JDK
  • jmod Pomáha pri práci so súbormi jmod. jmod je nový formát na balenie modulov. Tento formát umožňuje zahrnúť natívny kód, konfiguračné súbory a ďalšie údaje, ktoré sa nezmestia do súborov JAR

5. Architektúra modulového systému

Modulový systém implementovaný v jazyku ich podporuje ako konštrukt najvyššej úrovne, rovnako ako balíčky. Vývojári môžu usporiadať svoj kód do modulov a deklarovať medzi nimi závislosti vo svojich definičných súboroch príslušných modulov.

Definičný súbor modulu s názvom modul-info.java, obsahuje:

  • jeho meno
  • balíčky, ktoré sprístupňuje verejne
  • moduly od ktorých to závisí
  • akékoľvek služby, ktoré spotrebúva
  • akákoľvek implementácia služby, ktorú poskytuje

Posledné dve položky vo vyššie uvedenom zozname sa bežne nepoužívajú. Používajú sa iba vtedy, keď sú služby poskytované a spotrebované prostredníctvom internetu java.util.ServiceLoader rozhranie.

Všeobecná štruktúra modulu vyzerá takto:

src | ---- com.baeldung.reader | | ---- modul-info.java | | ---- com | | ---- baeldung | | ---- čítačka | | ---- Test.java | ---- com.baeldung.writer | ---- module-info.java | ---- com | ---- baeldung | ---- spisovateľ | --- -AnotherTest.java

Vyššie uvedená ilustrácia definuje dva moduly: com.baeldung.citovateľ a com.baeldung.spisovateľ. Každá z nich má svoju definíciu uvedenú v modul-info.java a súbory kódu umiestnené pod com / baeldung / čitateľ a com / baeldung / spisovateľ, resp.

5.1. Terminológie definície modulu

Pozrime sa na niektoré terminológie; použijeme pri definovaní modulu (t. j. v rámci modul-info.java):

  • modul: definičný súbor modulu začína týmto kľúčovým slovom, za ktorým nasleduje jeho názov a definícia
  • vyžaduje: sa používa na označenie modulov, od ktorých závisí; za týmto kľúčovým slovom musí byť uvedený názov modulu
  • tranzitívny: je uvedené za vyžaduje kľúčové slovo; to znamená, že akýkoľvek modul, ktorý závisí od definovania modulu vyžaduje tranzitívne dostane implicitnú závislosť na <názov modulu>
  • vývoz: slúži na označenie verejne dostupných balíkov v rámci modulu; za týmto kľúčovým slovom musí byť uvedený názov balíka
  • otvára: sa používa na označenie balíkov, ktoré sú prístupné iba za behu programu a sú tiež dostupné na introspekciu prostredníctvom rozhraní Reflection API; to je dosť významné pre knižnice ako Spring a Hibernate, ktoré sa veľmi spoliehajú na Reflection API; otvára je možné použiť aj na úrovni modulu, v takom prípade je celý modul prístupný za behu programu
  • používa: sa používa na označenie servisného rozhrania, ktoré tento modul používa; za týmto kľúčovým slovom sa musí zadať názov typu, t. j. úplný názov triedy / rozhrania
  • poskytuje ... s ..: používajú sa na označenie toho, že poskytuje implementácie, identifikované po s kľúčové slovo pre rozhranie služby identifikované po poskytuje kľúčové slovo

6. Jednoduchá modulárna aplikácia

Vytvorme jednoduchú modulárnu aplikáciu s modulmi a ich závislosťami, ako je uvedené v nasledujúcom diagrame:

The com.baeldung.student.model je koreňový modul. Definuje modelovú triedu com.baeldung.student.model.Student, ktorá obsahuje nasledujúce vlastnosti:

verejná trieda Student {private String registrationId; // ďalšie príslušné polia, getre a setteri}

Poskytuje ďalšie moduly typov definovaných v com.baeldung.student.model balíček. To sa dosiahne definovaním v súbore modul-info.java:

modul com.baeldung.student.model {exportuje com.baeldung.student.model; }

The com.baeldung.student.service modul poskytuje rozhranie com.baeldung.student.service.StudentService s abstraktnými operáciami CRUD:

verejné rozhranie StudentService {public String create (Student student); verejné čítanie študentov (String registrationId); verejná aktualizácia študenta (študent); verejné vymazanie reťazca (String registrationId); }

Závisí to od com.baeldung.student.model modul a robí typy definované v balíku com.baeldung.student.service dostupné pre ďalšie moduly:

modul com.baeldung.student.service {vyžaduje tranzitívny com.baeldung.student.model; export com.baeldung.student.service; }

Poskytujeme ďalší modul com.baeldung.student.service.dbimpl, ktorá zabezpečuje implementáciu com.baeldung.student.service.dbimpl.StudentDbService pre vyššie uvedený modul:

public class StudentDbService implementuje StudentService {public String create (Student student) {// Vytváranie študenta v databáze DB return student.getRegistrationId (); } verejné Študent čítať (String registrationId) {// Čítanie študenta z DB vrátiť nový Student (); } public Aktualizácia študenta (Student student) {// Aktualizácia študenta v DB spiatočný študent; } public String delete (String registrationId) {// Vymazanie študenta v databáze DB return registrationId; }}

Závisí to priamo od com.baeldung.student.service a prechodne ďalej com.baeldung.student.model a jeho definícia bude:

modul com.baeldung.student.service.dbimpl {vyžaduje tranzitívny com.baeldung.student.service; vyžaduje java.logovanie; export com.baeldung.student.service.dbimpl; }

Posledným modulom je klientský modul, ktorý využíva modul implementácie služby com.baeldung.student.service.dbimpl vykonávať svoje operácie:

public class StudentClient {public static void main (String [] args) {StudentService service = new StudentDbService (); service.create (nový študent ()); service.read ("17SS0001"); service.update (new Student ()); service.delete ("17SS0001"); }}

A jeho definícia je:

modul com.baeldung.student.client {vyžaduje com.baeldung.student.service.dbimpl; }

7. Zostavenie a spustenie vzorky

Poskytli sme skripty na kompiláciu a spustenie vyššie uvedených modulov pre platformy Windows a Unix. Tieto nájdete pod jadro-java-9 projekt tu. Poradie vykonania pre platformu Windows je:

  1. zostaviť-študent-model
  2. zostaviť-študent-služba
  3. compile-student-service-dbimpl
  4. zostaviť-študent-klient
  5. run-student-client

Poradie vykonania pre platformu Linux je celkom jednoduché:

  1. kompilačné moduly
  2. run-student-client

Vo vyššie uvedených skriptoch sa zoznámite s nasledujúcimi dvoma argumentmi príkazového riadku:

  • –Modul-zdroj-cesta
  • –Modul-cesta

Java 9 sa zbavuje konceptu classpath a namiesto toho zavádza cestu k modulu. Táto cesta predstavuje miesto, kde je možné moduly nájsť.

Môžeme to nastaviť pomocou argumentu príkazového riadku: –Modul-cesta.

Na zostavenie viacerých modulov naraz používame –Modul-zdroj-cesta. Tento argument sa používa na zadanie umiestnenia zdrojového kódu modulu.

8. Modulový systém použitý pre zdroj JDK

Každá inštalácia JDK sa dodáva s src.zip. Tento archív obsahuje kódovú základňu pre JDK Java API. Ak rozbalíte archív, nájdete viac priečinkov, z ktorých niekoľko začína java, málo s javafx a zvyšok s jdk. Každý priečinok predstavuje modul.

Moduly začínajúce sa java sú moduly JDK, tie, ktoré začínajú na javafx sú moduly JavaFX a ďalšie, začínajúce sa jdk sú moduly nástrojov JDK.

Všetky moduly JDK a všetky užívateľom definované moduly implicitne závisia od java.base modul. The java.base modul obsahuje bežne používané JDK API ako Utils, Collections, IO, Concurrency a ďalšie. Graf závislostí modulov JDK je:

Môžete sa tiež pozrieť na definície modulov JDK, aby ste získali predstavu o syntaxe ich definovania v priečinku modul-info.java.

9. Záver

V tomto článku sme sa pozreli na vytvorenie, kompiláciu a spustenie jednoduchej modulárnej aplikácie. Videli sme tiež, ako bol modulovaný zdrojový kód JDK.

Existuje niekoľko ďalších zaujímavých funkcií, ako napríklad vytváranie menších prevádzkových časov pomocou nástroja na prepájanie - jlink a okrem iných funkcií aj vytváranie modulárnych nádob. S týmito funkciami vás podrobne oboznámime v budúcich článkoch.

Project Jigsaw je obrovská zmena a my si budeme musieť počkať a sledovať, ako ho prijme ekosystém vývojárov, najmä s nástrojmi a tvorcami knižníc.

Kód použitý v tomto článku nájdete na GitHub.