Uvod u projekt Jigsaw

1. Uvod

Project Jigsaw krovni je projekt s novim značajkama usmjerenim na dva aspekta:

  • uvođenje modularnog sustava na jeziku Java
  • i njegova implementacija u JDK izvor i Java runtime

U ovom ćemo vas članku upoznati s projektom Jigsaw i njegovim značajkama i na kraju završiti jednostavnom modularnom aplikacijom.

2. Modularnost

Jednostavno rečeno, modularnost je princip dizajna koji nam pomaže postići:

  • labava spojnica između komponenata
  • jasni ugovori i ovisnosti između komponenata
  • skrivena implementacija pomoću jake inkapsulacije

2.1. Jedinica modularnosti

Sada dolazi pitanje o tome koja je jedinica modularnosti? U svijetu Jave, posebno s OSGi-om, JAR-ovi su se smatrali jedinicom modularnosti.

JAR-ovi su pomogli u grupiranju povezanih komponenata, ali imaju neka ograničenja:

  • izričiti ugovori i ovisnosti između JAR-ova
  • slaba enkapsulacija elemenata unutar JAR-ova

2.2. JAR Pakao

Pojavio se još jedan problem s JAR-ovima - JAR pakao. Višestruke verzije JAR-ova koji leže na stazi, rezultirale su ClassLoader učitavanje prve pronađene klase iz JAR-a, s vrlo neočekivanim rezultatima.

Drugi problem s JVM-om koji koristi classpath bio je taj da bi kompilacija aplikacije bila uspješna, ali aplikacija neće uspjeti tijekom izvođenja s ClassNotFoundException, zbog nestalih JAR-ova na stazi za vrijeme izvođenja.

2.3. Nova jedinica modularnosti

Uz sva ta ograničenja, kada su koristili JAR kao jedinicu modularnosti, tvorci Java jezika smislili su novu konstrukciju na jeziku koji se naziva moduli. A s tim je za Java planiran cijeli novi modularni sustav.

3. Jigsaw projekta

Primarni motivi za ovaj projekt su:

  • stvoriti modulni sustav za jezik - provedeno prema JEP 261
  • primijenite na izvor JDK - provedeno pod JEP 201
  • modularizirati JDKknjižnice - provedeno pod JEP 200
  • ažurirajte vrijeme izvođenja kako bi podržalo modularnost - provedeno pod JEP 220
  • biti u mogućnosti stvoriti manje vrijeme izvođenja s podskupom modula iz JDK - provedeno pod JEP 282

Druga važna inicijativa je inkapsulacija internih API-ja u JDK, onih koji su pod Sunce.* paketi i drugi nestandardni API-ji. Ovi API-ji nikada nisu trebali biti javno korišteni i nikada nije planirano njihovo održavanje. Ali snaga ovih API-ja natjerala je Java programere da ih iskoriste u razvoju različitih knjižnica, okvira i alata. Predviđene su zamjene za nekoliko internih API-ja, a ostali su premješteni u interne module.

4. Novi alati za modularnost

  • jdeps - pomaže u analizi baze koda za prepoznavanje ovisnosti o JDK API-ima i JAR-ovima treće strane. Također se spominje naziv modula u kojem se može pronaći JDK API. To olakšava modularizaciju baze koda
  • jdeprscan - pomaže u analizi baze koda za uporabu bilo kojeg zastarjelog API-ja
  • jlink - pomaže u stvaranju manjeg vremena izvođenja kombiniranjem modula aplikacije i JDK
  • jmod - pomaže u radu s jmod datotekama. jmod je novi format za pakiranje modula. Ovaj format omogućuje uključivanje izvornog koda, konfiguracijskih datoteka i ostalih podataka koji se ne uklapaju u JAR datoteke

5. Arhitektura sustava modula

Sustav modula, implementiran na jeziku, podržava ih kao konstrukciju najviše razine, baš kao i paketi. Programeri mogu organizirati svoj kod u module i deklarirati ovisnosti među njima u svojim datotekama definicije modula.

Datoteka definicije modula, nazvana kao module-info.java, sadrži:

  • to je ime
  • pakete koje javno stavlja na raspolaganje
  • moduli o kojima ovisi
  • bilo koje usluge koje troši
  • bilo koju provedbu usluge koju pruža

Posljednje dvije stavke s gornjeg popisa nisu često korištene. Koriste se samo kada se usluge pružaju i konzumiraju putem java.util.ServiceLoader sučelje.

Opća struktura modula izgleda ovako:

src | ---- com.baeldung.reader | | ---- module-info.java | | ---- com | | ---- baeldung | | ---- čitač | | ---- Test.java | ---- com.baeldung.writer | ---- module-info.java | ---- com | ---- baeldung | ---- pisač | --- -A AnotherTest.java

Gornja ilustracija definira dva modula: com.baeldung.reader i com.baeldung.writer. Svaka od njih ima svoju definiciju navedenu u module-info.java i kodne datoteke smještene pod com / baeldung / čitač i com / baeldung / pisac, odnosno.

5.1. Terminologije definicija modula

Pogledajmo neke terminologije; koristit ćemo tijekom definiranja modula (tj. unutar module-info.java):

  • modul: datoteka definicije modula započinje s ovom ključnom riječi nakon čega slijedi njezino ime i definicija
  • zahtijeva: koristi se za označavanje modula o kojima ovisi; nakon ove ključne riječi mora se navesti ime modula
  • prijelazni: navodi se nakon zahtijeva ključna riječ; to znači da svaki modul koji ovisi o definiranju modula zahtijeva prijelazno dobiva implicitnu ovisnost o <ime modula>
  • izvoz: koristi se za označavanje javno dostupnih paketa unutar modula; nakon ove ključne riječi mora se navesti naziv paketa
  • otvara: koristi se za označavanje paketa koji su dostupni samo u vrijeme izvođenja i koji su također dostupni za introspekciju putem Reflection API-ja; ovo je prilično značajno za knjižnice kao što su Spring i Hibernate, visoko se oslanjaju na API-je Reflection; otvara također se može koristiti na razini modula; u tom je slučaju čitav modul dostupan tijekom izvođenja
  • koristi: koristi se za označavanje uslužnog sučelja koje koristi ovaj modul; nakon ove ključne riječi mora se navesti naziv tipa, tj. cjeloviti naziv klase / sučelja
  • pruža ... s ...: koriste se za označavanje da pruža implementacije, identificirane nakon s ključna riječ za uslužno sučelje identificirano nakon pruža ključna riječ

6. Jednostavna modularna aplikacija

Stvorimo jednostavnu modularnu aplikaciju s modulima i njihovim ovisnostima kako je prikazano na donjem dijagramu:

The com.baeldung.student.model je korijenski modul. Definira klasu modela com.baeldung.student.model.Student, koji sadrži sljedeća svojstva:

javni razred Student {private String registrationId; // ostala relevantna polja, geteri i postavljači}

Pruža ostale module s vrstama definiranim u com.baeldung.student.model paket. To se postiže definiranjem u datoteci module-info.java:

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

The com.baeldung.student.service modul pruža sučelje com.baeldung.student.service.StudentService sa apstraktnim CRUD operacijama:

javno sučelje StudentService {stvoriti javni niz (student student); javno čitanje učenika (String registrationId); javno ažuriranje za studente (student student); javni String delete (String registrationId); }

Ovisi o com.baeldung.student.model modul i čini vrste definirane u paketu com.baeldung.student.service dostupno za ostale module:

modul com.baeldung.student.service {zahtijeva prijelazni com.baeldung.student.model; izvozi com.baeldung.student.service; }

Pružamo još jedan modul com.baeldung.student.service.dbimpl, koji osigurava provedbu com.baeldung.student.service.dbimpl.StudentDbService za gornji modul:

javna klasa StudentDbService implementira StudentService {public String create (Student student) {// Stvaranje učenika u DB-u return student.getRegistrationId (); } javno čitanje učenika (String registrationId) {// čitanje studenta iz DB-a return new Student (); } javno ažuriranje učenika (student student) {// ažuriranje studenta u DB return student; } public String delete (String registrationId) {// Brisanje učenika u DB-u return registrationId; }}

To izravno ovisi o com.baeldung.student.service a prijelazno dalje com.baeldung.student.model a njegova definicija bit će:

modul com.baeldung.student.service.dbimpl {zahtijeva prijelazni com.baeldung.student.service; zahtijeva java.logging; izvozi com.baeldung.student.service.dbimpl; }

Posljednji modul je klijentski modul - koji koristi modul za implementaciju usluge com.baeldung.student.service.dbimpl za obavljanje svojih operacija:

javna klasa StudentClient {javna statička void main (String [] args) {StudentService service = new StudentDbService (); service.create (novi Student ()); service.read ("17SS0001"); service.update (novi Student ()); service.delete ("17SS0001"); }}

A njegova definicija je:

modul com.baeldung.student.client {zahtijeva com.baeldung.student.service.dbimpl; }

7. Sastavljanje i pokretanje uzorka

Osigurali smo skripte za kompajliranje i pokretanje gornjih modula za Windows i Unix platforme. Oni se mogu naći u jezgra-java-9 projekt ovdje. Redoslijed izvršavanja za Windows platformu je:

  1. sastaviti-učenik-model
  2. sastaviti-student-servis
  3. sastaviti-student-servis-dbimpl
  4. sastaviti-student-klijent
  5. trčanje-student-klijent

Redoslijed izvršavanja za Linux platformu je prilično jednostavan:

  1. moduli za kompajliranje
  2. trčanje-student-klijent

U gornjim skriptama upoznat ćete se sa sljedeća dva argumenta naredbenog retka:

  • –Modul-izvor-put
  • –Modul-put

Java 9 ukida koncept classpath i umjesto toga uvodi put modula. Ova je staza mjesto na kojem se mogu otkriti moduli.

To možemo postaviti pomoću argumenta naredbenog retka: –Modul-put.

Za kompajliranje više modula odjednom koristimo –Modul-izvor-put. Ovaj se argument koristi za osiguravanje mjesta izvornog koda modula.

8. Sustav modula primijenjen na izvor JDK

Svaka JDK instalacija isporučuje se s src.zip. Ova arhiva sadrži bazu koda za JDK Java API-je. Ako izvučete arhivu, pronaći ćete više mapa, od kojih nekoliko počinje Java, malo sa javafx a ostalo sa jdk. Svaka mapa predstavlja modul.

Moduli koji počinju sa Java su JDK moduli, oni koji počinju sa javafx su JavaFX moduli i drugi koji počinju sa jdk su moduli alata JDK.

Svi JDK moduli i svi korisnički definirani moduli implicitno ovise o java.baza modul. The java.baza modul sadrži često korištene JDK API-je poput Utils, Collections, IO, Concurrency, između ostalog. Grafikon ovisnosti JDK modula je:

Također možete pogledati definicije JDK modula da biste dobili ideju o sintaksi za njihovo definiranje u module-info.java.

9. Zaključak

U ovom smo članku pogledali stvaranje, sastavljanje i pokretanje jednostavne modularne aplikacije. Također smo vidjeli kako je izvorni kod JDK moduliran.

Nekoliko je uzbudljivijih značajki, poput stvaranja manjeg vremena izvođenja pomoću alata za povezivanje - jlink i stvaranje modularnih staklenki među ostalim značajkama. Pobliže ćemo vas upoznati s tim značajkama u budućim člancima.

Projekt Jigsaw velika je promjena i morat ćemo pričekati i gledati kako će ga prihvatiti razvojni ekosustav, posebno s alatima i stvaraocima knjižnica.

Kôd korišten u ovom članku možete pronaći na GitHubu.