SLF4J est une couche d'abstraction du framework journal, qui lie des cadres journaux spécifiques, tels que log4j, journal de connexion, API de journalisation Java, etc. SLF4J a également sa propre implémentation par défaut, mais nous utilisons toujours principalement SLF4J comme couche d'abstraction du cadre journal.
Pour utiliser SLF4J, vous devez inclure une dépendance à "org.slf4j: slf4j-api".
Un simple examen du modèle de façade
SLF4J est une application typique du mode FACADE, donc avant de parler de SLF4J, passons en revue brièvement le mode FACADE.
Le mode de façade, dont le noyau est que la communication avec un sous-système doit être effectuée via un objet d'apparence unifié, ce qui rend le sous-système plus facile à utiliser. La structure du motif de vitrine est utilisée pour représenter une image:
Le cœur du mode FACADE est la façade, c'est-à-dire l'objet de façade, et le cœur de l'objet FACADE est plusieurs points:
D'une manière générale, le simple fait de revoir le mode magasin est suffisant ici, et vous commencerez à apprendre SLF4J ensuite.
Pourquoi utilisons-nous SLF4J
Pourquoi utilisons-nous SLF4J? Par exemple:
Nous utilisons la journalisation dans notre propre système
Notre système utilise A.Jar, et le système de journal utilisé dans A.Jar est log4j
Notre système utilise à nouveau B.Jar et le système de journal utilisé dans B.Jar est SLF4J-Simple
De cette façon, notre système doit prendre en charge et maintenir trois cadres de journal: Logback, Log4j et Slf4j-Simple en même temps, ce qui est très gênant.
La façon de résoudre ce problème est d'introduire une couche d'adaptation, qui détermine le système de journal à utiliser, et l'appelant doit seulement faire est d'imprimer le journal sans se soucier de la façon d'imprimer le journal. SLF4J ou Commons-Logging est cette couche d'adaptation, et SLF4J est l'objet de cet article.
D'après la description ci-dessus, nous devons clairement savoir une chose: SLF4J n'est qu'une norme de journalisation, pas une implémentation spécifique du système de journalisation. Il est très important de comprendre cette phrase. SLF4J ne mentionne que deux choses:
SLF4J-Simple et Logback sont tous deux des implémentations spécifiques de SLF4J. Log4j n'implémente pas directement SLF4J, mais il existe un pont spécial de première couche SLF4J-LOG4J12 pour implémenter SLF4J.
Afin de mieux comprendre SLF4J, nous regardons d'abord les exemples, puis lions le code source. Je crois que les lecteurs auront une compréhension plus approfondie de SLF4J.
Exemple d'application SLF4J
Comme mentionné ci-dessus, l'implémentation directe / indirecte de SLF4J comprend SLF4J-Simple, Logback, SLF4J-LOG4J12. Définissons d'abord un pom.xml et introduisons le package JAR pertinent:
<! - Texte d'origine: Cangjie en mai http://www.cnblogs.com/xrq730/p/8619156.html -> <project xmlns = "http://maven.apache.org/pom/4.0.0" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" xsi: schemalocation = "http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <ModelVersion> 4.0.0 </ ModelVersion> <ProupId> org.xrq.log </proncId> <ArtifactId> Log-Test </ ArtifactId> <Dersion> 1.0.0 </ Version> <packaging> Jar </ Packaging> <name> Log-Test </name> <url> http://maven.apache.org </ url> <url> http://maven.apache.org </ url> <project.build.sourceencoding> utf-8 </project.build.sourceencoding> </properties> <dedences> <dependency> <proupId> JUnit </proupId> <ArtefactId> JUnit </letefactId> <Dederneng <GroupId> org.slf4j </prôdId> <Artifactid> SLF4J-API </ artifactId> <Dersion> 1.7.25 </ Version> </ Dependency> <Dedency> <ProupId> Ch.qos.logback </prouventid> <ArtifActid> LOGBACK-CLASSIC </ Artifactid> <version> 1.2.3. <GroupId> org.slf4j </proupId> <Artifactid> slf4j-simple </ artifactId> <Dersion> 1.7.25 </-version> </ Dependency> <Dedency> <ProupID> LOG4J </proupId> <Ertifactid> LOG4J </ Artifactid> <version> 1.2.17 </DERNIFROITIONS> </DEFENCENCY> <GroupId> org.slf4j </rom grouped> <Artifactid> SLF4J-LOG4J12 </ Artifactid> <DERNÉRATEUR> 1.7.21 </ version> </Dependency> </Dependance> </randing>
Écrivez un code Java simple:
@TestPublic void testslf4j () {logger logger = loggerfactory.getLogger (object.class); Logger.Error ("123"); }Ensuite, nous commençons d'abord les lignes 30 à 49 de pom.xml ci-dessus, c'est-à-dire que nous n'introduisons aucune classe d'implémentation SLF4J et exécutons la méthode de test. Jetons un coup d'œil à la sortie de la console comme:
En voyant la sortie sans journaux, cela vérifie notre vue: SLF4J ne fournit pas une implémentation spécifique des journaux, et seul SLF4J ne peut pas imprimer des journaux.
Ouvrez ensuite l'annotation de classe-classique et exécutez la méthode de test. Jetons un coup d'œil à la sortie de la console comme:
J'ai vu que nous avons juste besoin d'introduire une classe d'implémentation spécifique de SLF4J, et nous pouvons utiliser le cadre du journal pour publier le journal.
Enfin, nous faisons un test. Nous ouvrons tous les journaux, introduisons la logback-classique, SLF4J-Simple, Log4j, exécutez la méthode de test et la sortie de la console est:
La différence par rapport à ce qui précède est que vous pouvez publier des journaux, mais certains journaux d'alarme seront sortis, ce qui nous incite à introduire plusieurs implémentations SLF4J en même temps, puis à sélectionner l'un d'entre eux comme système de journaux que nous utilisons.
D'après l'exemple, nous pouvons tirer une conclusion importante, c'est-à-dire le rôle de SLF4J: tant que tout le code utilise l'objet FACADE SLF4J, nous n'avons pas besoin de nous soucier de son implémentation spécifique. En fin de compte, une implémentation spécifique peut être utilisée à tous les endroits, et le remplacement et la maintenance sont très pratiques.
Principe de mise en œuvre de SLF4J
J'ai examiné l'exemple SLF4J ci-dessus, et j'étudierai la mise en œuvre de SLF4J ci-dessous. Nous ne nous concentrerons que sur le code clé.
L'utilisation de SLF4J est une phrase qui reste inchangée toute l'année, "Logger Logger = LoggerFactory.getLogger (object.class);", qui montre qu'il s'agit d'utiliser LoggerFactory pour obtenir l'implémentation spécifique d'une interface logique fournie par SLF4J. La méthode GetLogger de LoggerFactory est implémentée comme:
Public Static Logger GetLogger (class <?> Clazz) {logger logger = getLogger (Clazz.getName ()); if (détect_logger_name_mismatch) {class <?> autocomputedCallingClass = util.getCallingClass (); if (AutoComputedCallingClass! = null && non-matchingClasses (Clazz, autocomputedCallingClass)) {util.Report (String.format ("Détected Logger Name Mismatch. Nom donné: /"% S / "; nom calculé: /"% S / ".", Logger.getName (), autocomptedCalledClass.Glass.Glass.)); Util.Report ("voir" + logger_name_mismatch_url + "pour une explication"); }} Retour logger;}Commencez par le code de la ligne 2 et suivez la méthode bind () à LoggerFactory:
private final static void bind () {try {set <url> statingLoggerBinderPathSet = null; // Sautez la vérification sous Android, voir aussi // http://jira.qos.ch/browse/slf4j-328 if (! isAndroid ()) {statingLoggerBinderPathSet = findpossiblestatingBinderPathSet (); reportMultipleBindingAmbiguité (StaticLoggerBinderPathSet); } // La ligne suivante fait la liaison statingLoggerBinder.getSingleton (); Initialisation_state = réussit_initialisation; reportActualBinding (staticLoggerBinderPathSet); fixeSubstituTeLoggers (); ReplayEvents (); // Libérez toutes les ressources dans subs_factory subs_factory.clear (); } catch (noclassDEffoundError ncde) {String msg = ncde.getMessage (); if (MessageConttainSorgslf4JIMPLSTATICLOGgerBinder (msg)) {initialisation_state = NOP_Fallback_Initialisation; Util.Report ("Impossible de charger la classe /"org.slf4j.impl.statingloggerbinder/". "); Util.Report ("Implémentation de la bûcheron défaillante pour l'Obersation (NOP)"); Util.Report ("voir" + no_statingloggerbinder_url + "pour plus de détails."); } else {faillitbinding (ncde); lancer ncde; }} catch (java.lang.nosuchMethoDerror nsme) {string msg = nsme.getMessage (); if (msg! = null && msg.contains ("org.slf4j.impl.statingLoggerBinder.getSingleton ()")) {initialisation_state = faillit_initialization; Util.Report ("SLF4J-API 1.6.x (ou ultérieure) est incompatible avec cette liaison."); Util.report ("Votre liaison est la version 1.5.5 ou plus tôt."); Util.Report ("Mettre à niveau votre liaison à la version 1.6.x."); } lancer nsme; } catch (exception e) {Failsbinding (e); Jetez un nouveau IllégalStateException ("échec d'initialisation inattendu", e); }}La ligne 7 de cet endroit est une clé, regardez le code:
SET STATIQUE <URL> FINDPOSSIBLESTATICLOGGERBINDERPATHSET () {// Utilisez le jeu au lieu de la liste afin de gérer le bogue # 138 // LinkedHashSet approprié ici car il préserve l'ordre d'insertion // Pendant l'itération Set <url> StaticLoggerBinderPathSet = New LinkedHashSet <url> (); essayez {classloader LoggerFactoryClassLoader = LoggerFactory.class.getClassloader (); Énumération <url> chemins; if (loggerFactoryClassLoader == null) {paths = classloadher.getSystemResources (static_logger_binder_path); } else {paths = loggerfactoryclassloadher.getResources (static_logger_binder_path); } while (paths.hasmoreElements ()) {url path = paths.nextElement (); staticLoggerBinderPathSet.add (chemin); }} catch (ioException ioe) {util.Report ("Erreur d'obtention de ressources de Path", ioe); } RETOUR STATICLOGgerBinderPathSet;}Le point clé de cet endroit est en fait le code sur la ligne 12. Lorsque Getlogger, vous irez sur ClassPath pour trouver STATIC_LOGGER_BINDER_PATH. La valeur static_logger_binder_path est "org / slf4j / impl / statingloggerbinder.class", c'est-à-dire toutes les implémentations SLF4J, sous le chemin de package JAR fourni, il doit y avoir "org / slf4j / impl / statingloggerbinder.class". Nous pouvons jeter un œil:
Nous ne pouvons pas éviter d'introduire plusieurs implémentations SLF4J dans le système en même temps, donc le lieu de réception est un ensemble. Vous devez noter qu'il y aura des avertissements lorsque la partie ci-dessus introduira Logback, SLF4J-Simple et Log4j en même temps que la démonstration:
En effet, il y a trois "org / slf4j / impl / staticloggerbinder.class" qui existent. À l'heure actuelle, la déclaration de sortie de la méthode ReportMultipleBindingAmbiguité:
private static void reportMultipleBindingAmbiguity (set <url> bindPathSet) {if (isAmbiguSStaticLoggerBinderPathSet (BinderPathSet)) {util.Report ("Class Path contient plusieurs liaisons SLF4J."); pour (chemin d'URL: bindPathSet) {util.Report ("Found liant dans [" + path + "]"); } Util.report ("voir" + multiple_bindings_url + "pour une explication."); }}Ensuite, les internautes peuvent demander, que dois-je faire s'il y a trois "org / slf4j / impl / statingloggerbinder.class" en même temps? Tout d'abord, il est déterminé que cela ne provoquera pas d'erreur de démarrage, et deuxièmement, pendant la compilation, le compilateur sélectionnera l'un des staticgerbinder.classe pour la liaison.
Enfin, StaticLoggerBinder est relativement simple. Différents staticgerbinders ont des implémentations différentes de GetLoggerFactory. Après avoir obtenu ILoggerFactory, appelez GetLogger et obtenez le journaliste spécifique. Vous pouvez utiliser Logger pour la sortie du journal.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.