Bevezetés a Jigsaw projektbe

1. Bemutatkozás

A Project Jigsaw egy olyan esernyőprojekt, amely két új szempontot tartalmaz:

  • modulrendszer bevezetése Java nyelven
  • és megvalósítása a JDK forrás- és Java futásidejében

Ebben a cikkben bemutatjuk a Jigsaw projektet és annak jellemzőit, majd egy egyszerű moduláris alkalmazással összefoglaljuk.

2. Modularitás

Egyszerűen fogalmazva, a modularitás olyan tervezési elv, amely segít elérni:

  • laza csatlakozás az alkatrészek között
  • egyértelmű szerződések és az összetevők közötti függőségek
  • rejtett megvalósítás erős kapszulázással

2.1. Modularitás mértékegysége

Most jön a kérdés, hogy mi a modularitás egysége? A Java világban, különösen az OSGi esetében, a JAR-okat tekintették a modularitás egységének.

A JAR-ok segítettek a kapcsolódó összetevők csoportosításában, de vannak bizonyos korlátozásaik:

  • kifejezett szerződések és függőségek a JAR-ok között
  • az elemek gyenge beágyazása a JAR-okba

2.2. JAR Hell

Volt egy másik probléma a JAR-okkal - a JAR pokol. Az osztályúton fekvő JAR-ok több változata eredményezte a ClassLoader az első megtalált osztály betöltése a JAR-ból, nagyon váratlan eredménnyel.

A classpath-t használó JVM másik problémája az volt, hogy az alkalmazás összeállítása sikeres lesz, de az alkalmazás futás közben nem fog sikerülni a ClassNotFoundException, futás közben az osztálypályán hiányzó JAR-ok miatt.

2.3. A modularitás új egysége

Mindezen korlátozások mellett, amikor a JAR-ot használják a modularitás egységeként, a Java nyelv készítői új konstrukcióval álltak elő a moduloknak nevezett nyelven. És ezzel egy teljesen új moduláris rendszert terveznek a Java számára.

3. Projekt Jigsaw

A projekt elsődleges motivációi a következők:

  • hozzon létre egy modulrendszert a nyelv számára - a JEP 261. alatt hajtják végre
  • alkalmazza a JDK forrásra - a JEP 201 keretében hajtják végre
  • modulálja a JDK-tkönyvtárak - a JEP 200 keretében hajtják végre
  • frissítse a futási időt a modularitás támogatására - a JEP 220 keretében hajtják végre
  • tudjon kisebb futási időt létrehozni a JDK moduljainak részhalmazával - a JEP 282. alatt hajtják végre

Egy másik fontos kezdeményezés a belső API-k beágyazása a JDK-ba, azok, akik az nap.* csomagok és más nem szabványos API-k. Ezeket az API-kat soha nem akarták a nyilvánosság számára használni, és soha nem tervezték, hogy fenntartsák őket. De ezeknek az API-knak az ereje arra késztette a Java fejlesztőket, hogy felhasználják őket a különböző könyvtárak, keretrendszerek és eszközök fejlesztésében. Néhány belső API-hoz cserét biztosítottak, a többit pedig belső modulokba helyezték át.

4. Új eszközök a modularitáshoz

  • jdeps - segít a kódbázis elemzésében a JDK API-k és a harmadik fél JAR-októl való függőségek azonosításában. Megemlíti annak a modulnak a nevét is, ahol a JDK API megtalálható. Ez megkönnyíti a kódalap modulizálását
  • jdeprscan - segít elemezni az elavult API-k használatának kódbázisát
  • jlink - az alkalmazás és a JDK moduljainak kombinálásával segít egy kisebb futási idő létrehozásában
  • jmod - segít a jmod fájlokkal való munkában. A jmod egy új formátum a modulok csomagolásához. Ez a formátum lehetővé teszi natív kód, konfigurációs fájlok és egyéb adatok beillesztését, amelyek nem illenek a JAR fájlokba

5. Modul Rendszerarchitektúra

A nyelvben megvalósított modulrendszer ezeket a csomagokhoz hasonlóan legfelső szintű konstrukcióként támogatja. A fejlesztők modulokba rendezhetik kódjukat, és a moduldefiníciós fájljaikban deklarálhatják közöttük a függőségeket.

Egy moduldefiníciós fájl, amelynek neve: module-info.java, a következőket tartalmazza:

  • annak a neve
  • az általa nyilvánosan hozzáférhetővé tett csomagokat
  • a modulok, melyektől függ
  • bármely általa igénybe vett szolgáltatás
  • az általa nyújtott szolgáltatás bármilyen megvalósítása

A fenti lista utolsó két elemét nem szokták használni. Ezeket csak akkor használják, ha a szolgáltatásokat a java.util.ServiceLoader felület.

A modul általános felépítése a következőképpen néz ki:

src | ---- com.baeldung.reader | | ---- module-info.java | | ---- com | | ---- baeldung | | ---- olvasó | | ---- Test.java | ---- com.baeldung.writer | ---- module-info.java | ---- com | ---- baeldung | ---- író | --- -Egy másik teszt.java

A fenti ábra két modult határoz meg: com.baeldung.reader és com.baeldung.writer. Mindegyiküknek meg van adva a definíciója module-info.java alatt elhelyezett kódfájlokat com / baeldung / reader és com / baeldung / íróill.

5.1. Modul Definíció Terminológiák

Nézzünk meg néhány terminológiát; a modul definiálása során fogjuk használni (vagyis a module-info.java):

  • modul: a moduldefiníciós fájl ezzel a kulcsszóval kezdődik, amelyet a neve és a definíció követ
  • igényel: a függő modulok jelzésére szolgál; e kulcsszó után meg kell adni a modul nevét
  • tranzitív: a igényel kulcsszó; ez azt jelenti, hogy bármely modul, amely a modul meghatározásától függ transzitív implicit függést kap a <-tólmodulnév>
  • export: a nyilvánosan elérhető modulban lévő csomagok megjelölésére szolgál; e kulcsszó után meg kell adni a csomag nevét
  • megnyílik: a csak futás közben elérhető és a Reflection API-n keresztül introspekcióra is elérhető csomagok megjelölésére szolgál; ez meglehetősen jelentős az olyan könyvtárak számára, mint a Spring és a Hibernate, amelyek nagymértékben támaszkodnak a Reflection API-kre; megnyílik modul szinten is használható, ebben az esetben a teljes modul futás közben elérhető
  • használ: a modul által használt szolgáltatási interfész jelzésére szolgál; egy típusnevet, azaz a teljes osztály / interfész nevet kell megadni a kulcsszó után
  • biztosítja….: arra használják, hogy jelezzék, hogy a val vel kulcsszó, a biztosítja kulcsszó

6. Egyszerű moduláris alkalmazás

Hozzunk létre egy egyszerű moduláris alkalmazást modulokkal és azok függőségeivel, az alábbi ábra szerint:

A com.baeldung.student.model a root modul. Meghatározza a modellosztályt com.baeldung.student.model.Student, amely a következő tulajdonságokat tartalmazza:

public class Student {private String registrationId; // egyéb releváns mezők, getterek és beállítók}

Más modulokat biztosít a programban meghatározott típusokkal com.baeldung.student.model csomag. Ezt úgy érjük el, hogy meghatározzuk a fájlban module-info.java:

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

A com.baeldung.student.service modul interfészt biztosít com.baeldung.student.service.StudentService absztrakt CRUD műveletekkel:

nyilvános felület StudentService {public String create (hallgató hallgató); public Student read (String registrationId); nyilvános hallgatói frissítés (hallgatói hallgató); nyilvános karakterlánc törlése (String registrationId); }

Attól függ com.baeldung.student.model modul, és elkészíti a csomagban definiált típusokat com.baeldung.student.service elérhető más modulokhoz:

modul com.baeldung.student.service {transzitív com.baeldung.student.model szükséges; exportálja a com.baeldung.student.service szolgáltatást; }

További modult biztosítunk com.baeldung.student.service.dbimpl, amely biztosítja a megvalósítást com.baeldung.student.service.dbimpl.StudentDbService a fenti modulhoz:

public class A StudentDbService megvalósítja a StudentService {public String create (Student student) {// Student létrehozása a DB-ben return student.getRegistrationId (); } public Student read (String registrationId) {// Diák olvasása a DB-ből return new Student (); } public Student update (Student student) {// Diák frissítése a DB visszatérő hallgatóban; } public String delete (String registrationId) {// Tanuló törlése a DB return registrationId-ben; }}

Közvetlenül attól függ com.baeldung.student.service és átmenetileg tovább com.baeldung.student.model és meghatározása a következő lesz:

modul com.baeldung.student.service.dbimpl {transzitív com.baeldung.student.service szükséges; java.logginget igényel; exportálja a com.baeldung.student.service.dbimpl; }

Az utolsó modul egy kliens modul - amely a szolgáltatás megvalósítási modult használja com.baeldung.student.service.dbimpl műveleteinek elvégzéséhez:

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

És meghatározása:

modul com.baeldung.student.client {szükséges com.baeldung.student.service.dbimpl; }

7. A minta összeállítása és futtatása

A fenti modulok fordításához és futtatásához szkripteket biztosítottunk a Windows és a Unix platformokhoz. Ezek megtalálhatók a core-java-9 projekt itt. A Windows platform végrehajtásának sorrendje:

  1. összeállítás-hallgató-modell
  2. összeállítás-hallgató-szolgáltatás
  3. compile-student-service-dbimpl
  4. összeállítás-hallgató-kliens
  5. run-student-client

A Linux platform végrehajtásának sorrendje meglehetősen egyszerű:

  1. fordító modulok
  2. run-student-client

A fenti szkriptekben a következő két parancssori argumentumot ismertetjük:

  • –Modul-forrás-útvonal
  • –Modul-út

A Java 9 felszámolja az osztályút fogalmát, és bevezeti a modul elérési útját. Ez az útvonal az a hely, ahol a modulok felfedezhetők.

Ezt a parancssori argumentummal állíthatjuk be: –Modul-út.

Több modul egyszerre történő fordításához használjuk a –Modul-forrás-útvonal. Ez az argumentum a modul forráskódjának megadására szolgál.

8. A JDK Forrásra alkalmazott modulrendszer

Minden JDK telepítéshez tartozik a src.zip. Ez az archívum tartalmazza a JDK Java API-k kódbázisát. Ha kibontja az archívumot, több mappát talál, néhány kezdőbetűvel Jáva, kevesen vannak javafx a többit pedig jdk. Minden mappa egy modult jelent.

A kezdő modulok Jáva a JDK modulok, amelyek a következőkkel kezdődnek javafx a JavaFX modulok és mások kezdődnek jdk a JDK eszközök moduljai.

Az összes JDK modul és az összes felhasználó által definiált modul implicit módon függ a java.base modul. A java.base modul tartalmaz olyan általánosan használt JDK API-kat, mint például az Utils, Collections, IO, Concurrency. A JDK modulok függőségi grafikonja:

Megtekintheti a JDK modulok definícióit is, hogy képet kapjon a szintaxisról a module-info.java.

9. Következtetés

Ebben a cikkben egy egyszerű moduláris alkalmazás létrehozását, fordítását és futtatását vizsgáltuk. Láttuk azt is, hogy miként modulálták a JDK forráskódját.

Kevés izgalmasabb funkció létezik, például kisebb futási idő létrehozása a linker eszköz - jlink használatával és moduláris üvegek létrehozása a többi funkció mellett. Ezeket a funkciókat a későbbi cikkekben részletesen bemutatjuk.

A Jigsaw projekt hatalmas változás, és várnunk kell, és meg kell néznünk, hogyan fogadja el a fejlesztői ökoszisztéma, különösen az eszközökkel és a könyvtár készítőivel.

A cikkben használt kód megtalálható a GitHub oldalon.