2013-02-19 9 views
6

Normalerweise definiere ich Logger wie folgt aus:Wie Logger mit Google Guice injizieren

private static final Logger logger = LoggerFactory.getLogger(MyClass.class); 

Aber wenn @Inject verwenden, müssen wir nicht statisch und nicht-final-Feld verwenden, wie:

@Inject 
private Logger logger; 

dh Logger wird in jeder Instanz dieser Klasse erstellt, auch Logger ist veränderbar. Kann es eine Möglichkeit geben, Logger statisch zu machen? Auch, wie ich Logger an bestimmte Klasse binden kann (ich benutze das Klassenobjekt beim Erstellen von Logger-Objekt von der Fabrik LoggerFactory.getLogger(MyClass.class);, wie Logger auf die gleiche Weise mit injizierenden erstellen?)?

+2

Aus welchem ​​Grund wird der Logger injiziert? Ist es nur etwas Tipparbeit zu vermeiden? –

Antwort

7

Bitte überprüfen Sie die Custom Injections auf Guice Wiki, gibt es eine komplette Log4J Beispiel.

EDIT: Sie können entweder ein static Feld oder ein final Feld für Ihren Logger verwenden, aber kein static final eins. Dies ist ein Java limitation.

auch vorsichtig sein, that:

final Felder Injizieren wird nicht empfohlen, weil die injizierte Wert nicht auf andere Threads sichtbar sein können.

haben, die nicht getestet, aber der Code in dem Artikel sollte für statische Felder gut funktionieren, obwohl Sie es durch das Loswerden von MembersInjector verbessern könnten und in den TypeListener alle es tun (da ein statisches Feld sein muss nur einmal einstellen).

Mit requestStaticInjection() werden Sie gezwungen, alle Ihre Klassen in einer Moduldatei aufzulisten - keine gute Idee, da Sie bald vergessen werden, eine hinzuzufügen.

OTOH Wenn Sie nur JUL unterstützen möchten, könnten Sie besser die built-in support verwenden (wie von Jeff erwähnt, nahm ich an, Sie wollten keine allgemeine Antwort, da Sie JUL nicht speziell in Ihrer Frage erwähnt haben).

+0

Ich finde den verknüpften Artikel in mehreren Aspekten fehlt: 1) Eine neue Anmerkung ist erforderlich.Für JUL können Sie @Inject (sowohl java.inject.Inject als auch Guice's) verwenden. 2) Es wird keine Konstruktorinjektion unterstützt, 3) keine Methodeninjektion wird unterstützt. 4) Superklassen werden nur von Hacks in den Kommentaren unterstützt. Zusammenfassung bisher: JUL-Support ist etwas Besonderes und kann nicht in gleicher Weise und Qualität auf andere Logging-Frameworks übertragen werden. –

+0

Tut mir leid, ich finde das nicht konstruktiv oder relevant für meine Anwsser. 1) Nein, es ist nicht möglich, dass Sie den Check einfach fallen lassen und alle Logger-Felder injizieren können. 2) Ja, aber wie erwarten Sie das mit Guice zu arbeiten? 3) Es wird unterstützt, können Sie die Klasse in beliebiger Weise überprüfen (z. B. nach Methoden suchen) –

+0

Mein Punkt, der für Ihre Antwort relevant ist, ist dies: Der verknüpfte Artikel hat seine Nachteile. Die dort vorgeschlagene Lösung unterstützt die Injektion nicht in der gleichen Weise wie Guice die Injektion an anderer Stelle unterstützt. Diese Unterschiede sollten klar sein _upfront_ und nicht nach den Fakten. Zumal der letzte Teil der Frage ("wie man erstellt ...") und die Verwendung von "@ Inject" genau diese IMO anspricht.
Ich nannte die drei Probleme, die ich in einem ähnlichen Fall hatte. Das ist nicht gegen dich, sondern nur für alle, die diese Lösung erforschen wollen - Wenn sie sagen: "Ich kann mit diesen Dingen leben." OK - sei willkommen. –

2

Wenn Sie Ihre Anwendung für die Abhängigkeitsinjektion entwerfen, besteht die beste Vorgehensweise darin, statische Felder und Methoden so weit wie möglich zu vermeiden. Dies ist so, dass Ihre Abhängigkeiten klarer sind und es so einfacher ist, Ihre realen Abhängigkeiten während der Tests und während der Entwicklung Ihrer Anwendung durch andere Instanzen zu ersetzen. Das ideale Verhalten besteht daher darin, statische Methoden und Felder (einschließlich Logger) so weit wie möglich zu vermeiden.

Guice, jedoch erlaubt Markierung Felder statisch und requesting injection of static fields when the Injector is created. Die Felder müssen veränderbar bleiben - final bedeutet nicht "endgültig außer Guice".

public class YourClass { 
    @Inject static Logger logger; 

    /* ... */ 
} 

public class YourModule extends AbstractModule { 
    @Override public void configure() { 
    /* YourClass.logger will work once you create your Injector. */ 
    requestStaticInjection(YourClass.class); 
    } 
} 

Guice bietet automatisch java.util.logger.Logger instances für Sie mit dem Klassennamen in sie eingebettet ist, aber das ist nur wegen a special case coded into Guice. Wenn Sie einen speziellen Logger haben wollen, wie in this SO question, müssen Sie die benutzerdefinierten Injektionen untersuchen, mit denen Jakub verbunden hat - aber wenn das ganze Ziel darin besteht, die Logger-Erstellung zu zentralisieren, können Sie sie einfach umgestalten in eine statische Fabrik auch außerhalb von Guice.

@LogToFile 
public class YourClass { 
    private static final Logger logger = YourLoggerFactory.create(YourClass.class); 

    /* ... */ 
} 

public class YourLoggerFactory { 
    private YourLoggerFactory { /* do not instantiate */ } 

    public Logger create(Class<?> clazz) { 
    if (clazz.getAnnotation(LogToFile.class) != null) { 
     return someImplementation(new File(...)); 
    } else { 
     return someOtherImplementation(); 
    } 
    } 
} 
+0

Ihre Lösung hat den Nachteil, dass der Name der Klasse 'Yourclass.class' in Ihrem Beispiel in allen Anwendungen konsistent bereitgestellt werden muss. Das könnte genau einer der Gründe sein, warum eine zentralisierte Injektion in Betracht gezogen wird und hilfreich ist - dieses Problem würde bei einer geeigneten Injektionsunterstützung nicht bestehen. –

+0

@ A.H. Beachten Sie, dass die Fähigkeit eines Anbieters oder einer Abhängigkeit, seine Einfügeseite zu bestimmen, [explizit und absichtlich als Feature abgelehnt wurde] (https://code.google.com/p/google-guice/issues/detail?id=27). In einem Instanzfeld könnten Sie 'this' verwenden, aber in einem statischen Kontext hat Java leider keine kürzere Syntax als der Klassenname selbst. Wenn Sie "richtige Injektionsunterstützung" finden oder erstellen, geben Sie sie bitte weiter - ich wäre sehr glücklich zu sehen, wie es funktioniert! –

+0

Beachten Sie, dass Guice * die Injektion von Endfeldern erlaubt, siehe meine Antwort oben für einen Link. –

Verwandte Themen