web-dev-qa-db-fra.com

Comment le simple ajout de slf4j à pom.xml enveloppe-t-il log4j?

D'après ce que j'ai vu dans les fichiers d'exemple spring pom.xml, c'est qu'ils ajoutent quelques entrées pour slf4j et log4j et d'une manière ou d'une autre, lorsque vous utilisez log4j dans votre application Spring, il sera enveloppé par la bibliothèque slf4j.

Quelqu'un peut-il m'expliquer comment cela se produit par magie?

22
codecompleting

Spring utilise toujours commons-logging pour toute la journalisation interne (rétrocompatibilité). Si vous souhaitez utiliser un autre cadre de journalisation (log4j) alors vous devez ponter les appels de commons logging à votre cadre de choix. Sinon, vous devrez gérer plusieurs configurations de journalisation.

slf4j agit comme une simple façade pour divers frameworks de journalisation (jul, log4j, jcl, logback) et vous permet de brancher le cadre de journalisation souhaité au moment du déploiement.

Au lieu d'utiliser l'implémentation du framework de journalisation imposée par le framework tiers, vous fournissez le slf4j's implémentation du pont qui agit comme la vraie chose mais qui transfère simplement les appels de journalisation à slf4j ou sa reliure concrète.

La section de journalisation de Maven pom.xml ressemble généralement à ceci:

<!-- remove the real commons-logging from classpath -->
<!-- declare as provided or exclude from spring jars -->
<dependency>
    <artifactId>commons-logging</artifactId>
    <groupId>commons-logging</groupId>
    <version>1.0</version>
    <scope>provided</scope>
</dependency>

<!-- add slf4j interfaces to classpath -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.6.4</version>
    <scope>compile</scope>
</dependency>

<!-- add commons logging to slf4j bridge to classpath --> 
<!-- acts as jcl but routes commons-logging calls to slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>1.6.4</version>
    <scope>runtime</scope>
</dependency>

<!-- add log4j binding to classpath -->
<!-- routes slf4j calls to log4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.4</version>
    <scope>runtime</scope>
</dependency>

<!-- add log4j to classpath -->
<!-- does the logging -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.16</version>
</dependency>

Cela n'a rien à voir avec le conteneur Spring ni avec l'injection de dépendances, c'est un pur chemin de classe, des trucs de chargeur de classe ...

Veuillez consulter lessuivants liens pour plus de détails.

29
Bruno Dević

slf4j est une API de journalisation, qui ne fait rien, juste un tas d'interfaces. log4j est un système de journalisation, avec des classes concrètes. Il y a un slf4j-log4j bibliothèque qui utilise log4j comme backend pour l'API slf4j.

Certains projets dépendent explicitement de log4j, ils appellent des classes concrètes. Ainsi, vous ne pouvez pas utiliser un autre backend (par exemple, logback ou j.u.l ou Apache commons ou autre) pour votre projet que vous avez judicieusement réalisé en utilisant uniquement l'API slf4j.

Il y a ne astuce pour remplacer les classes log4j par une implémentation fictive (le pont) qui redirige simplement tous les appels vers le sl4j. Dans maven, vous déclarez simplement une dépendance avec un numéro de version très élevé et cette maquette considérée comme une bibliothèque log4j ultra-moderne.

5
kan