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:
- sastaviti-učenik-model
- sastaviti-student-servis
- sastaviti-student-servis-dbimpl
- sastaviti-student-klijent
- trčanje-student-klijent
Redoslijed izvršavanja za Linux platformu je prilično jednostavan:
- moduli za kompajliranje
- 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.