Module [Java]
Qu'est-ce qu'un module?
- Package concept superordonné
- Constitution
- ** Packages et ressources associées **
- Fichier de définition de module qui définit ses propres informations de configuration **
Problèmes d'emballage traditionnels
Les droits d'accès ne peuvent pas être définis pour chaque package
- Pour les packages censés être utilisés à l'intérieur de la bibliothèque, je souhaite empêcher l'accès depuis l'extérieur de la bibliothèque.
- Mais il n'y a aucun moyen de rendre invisible la ** classe publique à usage interne **
Le fichier .jar ne peut pas représenter les dépendances
- Plusieurs packages sont combinés sous forme de fichier compressé au format .jar et fournis sous forme de bibliothèque.
- Mais .jar ne peut pas exprimer les dépendances entre les bibliothèques
- Dans le .jar ** Je ne sais pas quel type d'API est censé être utilisé de l'extérieur ou quelle bibliothèque est nécessaire pour l'opération **
Résolu en utilisant des modules!
- ** Regroupez des bibliothèques et des frameworks spécifiques en groupes **
- La bibliothèque modulaire permet une gestion plus fine des classes publiques
- ** Public ** uniquement dans le module actuel
- ** Public ** uniquement pour des modules spécifiques
- ** Public pour tous les modules (comme avant) **
Module de base
- Décrivez le fichier de définition du module avec ** module-info.java ** directement sous / sec
- ** Répertorier les packages dont dépend le module, les informations sur les packages qui sont exposées à l'extérieur **
- Le type java.net.http.HttpRequest n'est pas accessible` si les bibliothèques requises ne sont pas déclarées dans require
module-info.java
//Nom du module foo
//java dans le module foo.net.besoin de http
module foo {
requires java.net.http;
requires mylib;
requires gson;
}
Module de bibliothèque standard
- La bibliothèque standard est également modulaire
Module de base
- java.base
- Il est difficile d'ajouter les bibliothèques standard une par une, donc ** Les paquets fréquemment utilisés sont regroupés dans le module java.base **
- Le module java.base est implicitement chargé donc aucune déclaration explicitement requise n'est requise
- Il existe également un ** module java.se ** qui définit toute la bibliothèque standard Java, mais il charge également les modules inutiles.
Dépendance transitionnelle
- ** Transitionnel **: Si le module chargé dépend d'un autre module, la destination dépendante est également chargée.
- ** nécessite transitive ** pour résoudre correctement les dépendances de transition
module-info.java
module java.se {
requires transitive java.compiler;
requires transitive java.datatranfer;
requires transitive java.desktop;
//Abréviation
}
Libération du package
- Si vous souhaitez publier votre package
- Il y a des packages (lib) que vous souhaitez publier à l'extérieur et des packages que vous utilisez dans la bibliothèque (interne)
- ** Seules les bibliothèques publiées dans la directive sur les exportations ** peuvent être publiées en externe
module-info.java
module mylib {
exports mylib.lib;
}
//OK
import mylib.lib.MainLib;
//NG! interna;Le paquet est invisible
//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;
}
Publication de package uniquement pour des modules spécifiques
- ** exporte le package vers le module **
- Dans les cas suivants, le paquet lib est uniquement exposé au module foo
- Plusieurs destinations de publication peuvent être spécifiées avec
,
module-info.java
module mylib {
exports mylib.lib to foo;
}
Méthode privée ouverte
- ** Réflexion profonde **: accès forcé par réflexion
- La réflexion profonde n'est pas possible avec les exportations de modules uniquement
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); //Erreur
System.out.println(name.get(m));
} catch (InstantiationException | IllegalAccessException |
IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException | NoSuchFieldException e) {
e.printStackTrace();
}
}
}
Déclarez un paquet avec ** la directive opens ** et résolvez-le!
- Publiez le package uniquement lors de l'exécution
- Lorsque vous faites référence à un type autre que la réflexion, incluez également la directive sur les exportations.
- **
open module mylib {
** ouvre tous les paquets sous le module
module-info.java
module mylib {
opens mylib.lib;
exports mylib.lib;
}
Module spécial
- Le concept de pseudo module est également fourni
- ** Module automatique **
- ** Module anonyme **
Module automatique
- Fichier .Jar situé dans le chemin du module
- Une bibliothèque qui n'a pas
module-info.java
Déterminé à partir des informations du manifeste
- Définit le nom spécifié dans l'attribut ** Automatic-Module-Name ** du fichier manifeste (META-INF / MANIFEST.MF) sur le nom du module.
MANIFEST.MF
Manifest-Version: 1.0
Automatic-Module-Name: hoge.bar
Déterminé par le nom de fichier .jar
- Règles de dénomination
- Suppression de l'extension
.jar
- Si les caractères après le trait d'union ne sont que des nombres / points, supprimez après le trait d'union
- Convertit les caractères non alphanumériques en «.»
- Les points de répétition sont des points simples, les points de début / de fin sont supprimés
- ex: hoge-bar-1.0.5.jar est ** hoge.bar **
- Règles de fonctionnement
- ** Exporte / ouvre tous les paquets en dessous **
- ** Tous les modules enregistrés dans le chemin du module et les modules anonymes sont requis **
- ** Nécessite requis pour utiliser les packages exportés / ouverts par module automatique à partir d'autres modules **
Module anonyme
- Fichier .Jar placé dans le chemin de classe
- N'a pas de nom de module
- Au moment de la compilation ** Ne peut pas être référencé à partir des modules d'application **
- ** Peut être référencé à partir de modules automatiques **
- ** Module d'application **: Module avec module-info.java
- ** Module de plate-forme **: modules qui composent la bibliothèque standard
Coexistence avec des bibliothèques non-modules
- ** Utilisez des bibliothèques non-module à partir d'applications modulaires **
- La ** bibliothèque Gson ** suivante convertit les objets Java en chaînes au format JSON
- dépend du package java.sql
- Réflexion profonde sur l'objet Java à convertir
- Vous ne pouvez pas accéder à la classe java.sql.Time sans référence au module java.sql utilisé en interne par Gson.
//Exemple NG Erreur d'exécution
import com.google.gson.Gson;
public class NoModuleLib {
public static void main(String[] args) {
var g = new Gson();
var a = new Article("Changements de Java 11", "https://codezine.jp/article/corner/751");
//Sortir le résultat de la conversion du contenu de l'objet en JSON
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("Titre:%s(%s)",
this.title, this.url);
}
}
Ajouter explicitement un module dans l'option d'exécution
- Dans l'argument VM de la configuration d'exécution
- **
--add-opens = nom du module / nom du package = modules autorisés
**
--add-modules=java.sql --add-opens=foo/example=gson
- Rendre l'exemple de package du module foo accessible depuis la bibliothèque gson