[[:oktatas:programozás:java|< Java]] ====== A Java modulrendszer ====== * **Szerző:** Sallai András * Copyright (c) 2025, Sallai András * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]] * Web: https://szit.hu ===== Bevezetés ===== A Java 9 Platform Module System, röviden JPMS. A Java 9-ben vezették be a modulok kezelésére. A modul nevét, függőségeit, láthatósági szabályait a **module-info.java** fájlban írjuk le. ==== Egy modul felépítése ==== Miket tartalmazhat egy modul? * osztályok * interfészek * csomagok * erőforrások Minden modul gyökérkönyvtárában lennie kell egy **module-info.java** fájlnak, például: module com.example { requires javafx.controls; requires javafx.fxml; exports com.example.ui; opens com.example.controllers to javafx.fxml; } ==== A module-info.java fő kulcsszavai ==== ^ Kulcsszó ^ Jelentés ^ | module | A modul neve (pl. com.example) | | require | Függőség megadása | | require transitive | A függőséget a modulunkat használók is elérhetik | | exports | Egy csomagot más modulok számára elérhető tesz | | opens | Egy csomagot reflektív hozzáférésre nyit meg. | | opens ... to | Egy csomagot célzottan egy adott modul számára nyit meg | | uses | A ServiceLoader((Dinamikus szolgáltatás betöltés a Java nyelvben)) által betöltött szolgáltatást jelez. | | provides ... with | Egy interfészt és annak megvalósítását \\ adja meg a ServiceLoader számára | ===== Egyszerű függőség ===== module com.example { requires java.sql; } ===== Tranzitív függőség ===== module com.example { requires transitive javafx.graphics; } ===== Csomagok exportálása ===== A com.example.api csomag látható más modulok számára. module com.example { exports com.example.api; } ===== Reflektív hozzáférés biztosítása ===== module com.example { opens com.example.model to com.google.gson; } Ez azt jelenti, hogy a com.example.model csomagot csak a Gson könyvtár érheti el reflektíven, más modulok nem. ===== Modulok között szolgáltatás nyújtá (ServiceLoader) ===== module com.example { provides com.example.MyService with com.example.impl.MyServiceImpl; } Ez azt jelenti, hogy a com.example.impl.MyServiceImpl osztály az com.example.MyService interfész megvalósítása. Ha egy másik modul ezt használni szeretné, így teheti meg: module com.client { requires com.example; uses com.example.MyService; } ===== Modulári és nem modulári könyvtárak használata ===== Ha egy nem moduláris (régi) JAR-t szeretnél használni, akkor: * Az --add-modules kapcsolóval futtatáskor hozzá lehet adni a modulpath-hoz. * Az Automatic-Module-Name attribútummal lehet segíteni a kompatibilitást. ===== Moduláris és nem moduláris alkalmazások közötti különbségek ===== ^ Jellemző ^ Moduláris alkalmazás ^ Hagyományos alkalmazás ^ | Modulok láthatóság | Csak exportált csomagok láthatók | Minden public látható | | Függőségek | A requires használatával szabályozott | Classpath alapján működik | | Egységbezárás | Jobban ellenőrizhető | Gyengébb láthatóság-kezelés | | Visszafelé kompatibilitás | Kezdeti nehézségek | Klasszikus Java mód | ===== Tranzitív függőség ===== Ha modulárisan programozunk, a modulunk neve lehet com.example, lan.zold, de nevezzük most egyszerűen "A" modulnak. A module-info.java fájlban egy függőséget így jelölhetünk meg: requires javafx.controls; vagy: requires javafx.fxml; Legyen egy másik modul, nevezzük "B" modulnak, amely használja az "A" modult. Ebben az esetben "B" nem fér hozzá javafx.controls és a javafx.fxml modulokhoz, mert azokat "A" csak saját használatra jelölte meg. Most vizsgáljunk meg egy másik függőséget: requires transitive javafx.graphics; Mivel "A" modul ezt a függőséget tranzitív módon jelöli meg, a "B" modul is automatikusan hozzáfér javafx.graphics modulhoz, anélkül, hogy külön requires javafx.graphics; sort kellen írnia. ===== Forrás ===== * https://www.oracle.com/corporate/features/understanding-java-9-modules.html (2025)