2012-10-26 3 views
4

Après une inspection superficielle, il semble que SLF4J et Guice (enfin, tout cadre DI, en fait) sont en quelque sorte des philosophies contradictoires. SLF4J prend l'approche "hey, nous ne saurons pas jusqu'à l'exécution quelles classes nous allons lier, et c'est OK" Guice, d'autre part, semble dire "hey, nous devons savoir à compile-time exactement à quelles classes nous nous lions ".Comment injecter des liaisons SLF4J avec Guice?

Donc je demande: est-il possible d'utiliser Guice/Spring/quel que soit le cadre DI pour configurer/injecter des liaisons SLF4J?

Le point de départ est que Java ClassLoader est ce qui "injecte" SLF4J à l'exécution avec le bon Logger/LoggerFactory/etc. objets, donc je ne peux pas comprendre comment injecter ces ClassLoaders afin qu'ils retournent le org.slf4j.impl.Logger que je veux à l'exécution:

Je demande parce que j'aime l'avantage de SLF4J et de se connecter à une API, mais aussi comme les avantages de DI. Y a-t-il un moyen de faire ce travail? Merci d'avance!

+0

Qu'essayez-vous exactement de faire? Essayez-vous d'utiliser Guice pour injecter 'Logger'? Injecter 'LoggerFactory'?Lier 'LoggerFactory' à une implémentation d'API particulière basée sur une configuration de Guice? (Je n'ai pas travaillé avec SLF4J auparavant, mais d'après ce que je peux dire, tous les trois sont viables.) –

Répondre

3

Je crois qu'il est impossible (à moins que vous faire quelque chose de très lourd, comme un conteneur qui crée classloader enfant pour votre application ... quelque chose comme ça)

L'idée de base de SLF4J d'avoir la mise en œuvre remplaçable par avoir le liant lib fournissant le org.slf4j.impl.StaticLoggerBinder et l'API SLF4J recherchera cette classe à travers le chargeur de classe. Par conséquent, s'il y a plus d'un classeur dans classpath, il n'y a aucun moyen de distinguer les org.slf4j.impl.StaticLoggerBinder qu'ils fournissent. La structure DI ne va pas aider à cela, étant donné que la structure de journalisation s'initialise avant même que DI ne se produise.

À moins que SLF4J ne change sa conception à l'avenir, il n'y a pas beaucoup de chemin que nous pouvons faire. Et, je doute qu'il est possible même SLF4J change son design. Comme nous n'avons aucun moyen de dire au conteneur DI que l'initialisation de Logging est quelque chose dont tout le monde dépend. Je crois qu'il y a plus de raisons qui rendent presque impossible d'atteindre. Cependant, ce dont je doute, est-ce que cela a vraiment quelque chose à voir avec DI? Honnêtement, je ne vois pas le problème de contrôler quelle liaison de journalisation utiliser en plaçant JAR correspondant dans classpath. Si vous voulez le contrôler à l'exécution, un peu par programmation, je pense que l'écriture d'un petit conteneur pour lancer votre application est la voie à suivre. Cependant, il n'a toujours rien à voir avec DI.

1

Une approche plutôt simple de ce problème consiste à injecter une instance ILoggerFactory dans LoggerFactory via la méthode setILoggerFactory(). (En date d'octobre 2012, la méthode setILoggerFactory() n'existe pas.)

Le mécanisme de liaison statique actuellement implémenté par SLF4J ne fait pas grand-chose d'autre que de définir le ILoggerFactory. Une telle approche fonctionnerait-elle pour vous?

1

Pour quiconque trouve cela maintenant: Sangria implémente un "classeur contextuel" qui fonctionne très bien pour cela; Voir sangria-slf4j et sangria-contextual spécifiquement.

De the author's blog post, vous pouvez mettre en place une usine de SLF4J nommé enregistreur aussi facilement que:

public class YourModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     install(new SangriaSlf4jModule()); 
    } 
} 

... et il y a des exemples de la façon d'utiliser les nouveaux fournisseurs pour vos propres types aussi bien.

+0

OP ne demande pas d'injecter des Loggers avec le nom en fonction du contexte. Il demande même la commutation de l'implémentation (aka liaison) de SLF4j. –

+0

Excellente trouvaille. Merci de l'avoir posté! – Cypher

Questions connexes