[Java] Modul
Was ist ein Modul?
- Paket übergeordnetes Konzept
- Verfassung
- ** Pakete und zugehörige Ressourcen **
- Moduldefinitionsdatei, die ihre eigenen Konfigurationsinformationen definiert **
Traditionelle Verpackungsprobleme
Zugriffsrechte können nicht für jedes Paket festgelegt werden
- Für Pakete, die innerhalb der Bibliothek verwendet werden sollen, möchte ich den Zugriff von außerhalb der Bibliothek verhindern.
- Es gibt jedoch keine Möglichkeit, die ** öffentliche Klasse für den internen Gebrauch unsichtbar zu machen **
Die JAR-Datei kann keine Abhängigkeiten darstellen
- Mehrere Pakete werden als komprimierte Datei im JAR-Format kombiniert und als Bibliothek bereitgestellt.
- .Jar kann jedoch keine Abhängigkeiten zwischen Bibliotheken ausdrücken
- In der .jar ** Ich weiß nicht, welche Art von API von außen verwendet werden soll oder welche Bibliothek für den Betrieb benötigt wird **
Gelöst mit Modulen!
- ** Bündeln Sie bestimmte Bibliotheken und Frameworks in Gruppen **
- Die modulare Bibliothek ermöglicht eine feinere Verwaltung öffentlicher Klassen
- ** Öffentlich ** nur im aktuellen Modul
- ** Öffentlich ** nur für bestimmte Module
- ** Öffentlich für alle Module (wie zuvor) **
Modul grundlegend
- Beschreiben Sie die Moduldefinitionsdatei mit ** module-info.java ** direkt unter / sec
- ** Listen Sie Pakete auf, von denen das Modul abhängt, Paketinformationen, die nach außen gerichtet sind **
- Wenn Sie die erforderlichen Bibliotheken nicht in require deklarieren, ist "Der Typ java.net.http.HttpRequest ist nicht zugänglich"
module-info.java
//Modulname foo
//Java im Foo-Modul.net.brauche http
module foo {
requires java.net.http;
requires mylib;
requires gson;
}
Standardbibliotheksmodul
- Die Standardbibliothek ist ebenfalls modularisiert
Grundmodul
- java.base
- Es ist mühsam, die Standardbibliotheken einzeln hinzuzufügen. ** Häufig verwendete Pakete werden im Modul java.base gruppiert. **
- Das Modul java.base wird implizit geladen, sodass keine explizite Deklaration erforderlich ist
- Es gibt auch ein ** java.se-Modul **, das die gesamte Java-Standardbibliothek definiert, aber auch unnötige Module lädt.
Übergangsabhängigkeit
- ** Übergang **: Wenn das geladene Modul von einem anderen Modul abhängig ist, wird auch das abhängige Ziel geladen.
- ** erfordert transitiv **, um Übergangsabhängigkeiten gut zu lösen
module-info.java
module java.se {
requires transitive java.compiler;
requires transitive java.datatranfer;
requires transitive java.desktop;
//Abkürzung
}
Paketfreigabe
- Wenn Sie Ihr Paket veröffentlichen möchten
- Es gibt Pakete (lib), die Sie nach außen veröffentlichen möchten, und Pakete, die Sie in der Bibliothek verwenden (intern).
- ** Nur in der Ausfuhrrichtlinie ** veröffentlichte Bibliotheken können extern veröffentlicht werden
module-info.java
module mylib {
exports mylib.lib;
}
//OK
import mylib.lib.MainLib;
//NG! interna;Paket ist unsichtbar
//import mylib.internal.Sublib;
public class ModuleClient {
public static void main(String[] args) {
var main = new MainLib();
main.run();
}
}
module foo {
requires java.net.http;
requires mylib;
requires gson;
}
Paketfreigabe nur für bestimmte Module
- ** exportiert Paket in Modul **
- In den folgenden Fällen ist das lib-Paket nur für das foo-Modul verfügbar
- Mit
,
können mehrere Veröffentlichungsziele angegeben werden
module-info.java
module mylib {
exports mylib.lib to foo;
}
Private Methode öffnen
- ** Deep Reflection **: Erzwungener Zugriff durch Reflektion
- Eine tiefe Reflexion ist allein mit Modulexporten nicht möglich
import java.lang.reflect.InvocationTargetException;
import mylib.lib.MainLib;
public class ModuleClient2 {
public static void main(String[] args) {
try {
var clazz = MainLib.class;
var con = clazz.getConstructor();
var m = con.newInstance();
var name = clazz.getDeclaredField("name");
name.setAccessible(true); //Error
System.out.println(name.get(m));
} catch (InstantiationException | IllegalAccessException |
IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}
Deklarieren Sie ein Paket mit ** öffnet Direktive ** und lösen Sie es!
- Veröffentlichen Sie das Paket nur zur Laufzeit
- Wenn Sie sich auf einen anderen Typ als Reflection beziehen, schließen Sie auch die Exportrichtlinie ein.
- **
open module mylib {
** öffnet alle Pakete unter dem Modul
module-info.java
module mylib {
opens mylib.lib;
exports mylib.lib;
}
Spezialmodul
- Pseudomodul-Konzept wird ebenfalls bereitgestellt
- ** Automatikmodul **
- ** Anonymes Modul **
Automatisches Modul
- .Jar-Datei im Modulpfad
- Eine Bibliothek ohne
module-info.java
Bestimmt aus Manifestinformationen
- Setzt den im Attribut ** Automatischer Modulname ** der Manifestdatei (META-INF / MANIFEST.MF) angegebenen Namen auf den Modulnamen.
MANIFEST.MF
Manifest-Version: 1.0
Automatic-Module-Name: hoge.bar
Bestimmt durch den Dateinamen .jar
- Namensregeln
- Die Erweiterung
.jar
wurde entfernt
- Wenn die Zeichen nach dem Bindestrich nur Zahlen / Punkte sind, löschen Sie sie nach dem Bindestrich
- Konvertieren Sie nicht alphanumerische Zeichen in "."
- Wiederholungspunkte sind einzelne Punkte, führende / nachfolgende Punkte werden entfernt
- Beispiel: hoge-bar-1.0.5.jar ist ** hoge.bar **
- Betriebsregeln
- ** Exportiert / öffnet alle Pakete darunter **
- ** Alle im Modulpfad registrierten Module und anonymen Module sind erforderlich **
- ** Erfordert die Verwendung von Paketen, die vom automatischen Modul aus anderen Modulen exportiert / geöffnet wurden **
Anonymes Modul
- .Jar-Datei im Klassenpfad platziert
- Hat keinen Modulnamen
- Zur Kompilierungszeit ** Kann nicht von Anwendungsmodulen referenziert werden **
- ** Kann von automatischen Modulen referenziert werden **
- ** Anwendungsmodul **: Modul mit module-info.java
- ** Plattformmodul **: Module, aus denen die Standardbibliothek besteht
Koexistenz mit Nicht-Modul-Bibliotheken
- ** Verwenden Sie Nicht-Modul-Bibliotheken aus modularen Apps **
- Die folgende ** Gson-Bibliothek ** konvertiert Java-Objekte in JSON-formatierte Zeichenfolgen
- java.sql-Paket abhängig
- Tiefe Reflexion über das zu konvertierende Java-Objekt
- Auf die Klasse java.sql.Time kann nicht ohne Verweis auf das von Gson intern verwendete Modul java.sql zugegriffen werden.
//NG-Beispiel Laufzeitfehler
import com.google.gson.Gson;
public class NoModuleLib {
public static void main(String[] args) {
var g = new Gson();
var a = new Article("Java 11 ändert sich", "https://codezine.jp/article/corner/751");
//Geben Sie das Ergebnis der Konvertierung des Objektinhalts in JSON aus
System.out.println(g.toJson(a));
}
}
Article.java
public class Article {
private String title;
private String url;
public Article(String title, String url) {
this.title = title;
this.url = url;
}
@Override
public String toString() {
return String.format("Titel:%s(%s)",
this.title, this.url);
}
}
Fügen Sie der Ausführungsoption explizit ein Modul hinzu
- Im VM-Argument der Ausführungskonfiguration
- **
--add-opens = Modulname / Paketname = zulässige Module
**
--add-modules=java.sql --add-opens=foo/example=gson
- Machen Sie das Beispielpaket des foo-Moduls über die gson-Bibliothek zugänglich