W tym samouczku Mkyong zaproponowano zainicjalizowanie rejestratorów w ten sposób:
@Controller
public class WelcomeController {
private static final Logger logger = Logger.getLogger(WelcomeController.class);
// etc
}
Prawdopodobnie teraz każda inna klasa, której używasz, ma program rejestrujący, zainicjuje swoje programy rejestrujące w ten sam sposób.
Moje pytanie brzmi - czy to najlepszy sposób, aby to zrobić? Wydaje się ... powtarzalne.
getLogger()
nazwę programu rejestrującego, aby uzyskać.Odpowiedzi:
Twój komentarz mówi, że „pełny” odnosi się do potrzeby powtarzania tego wiersza kodu w każdej klasie. Moja pierwsza odpowiedź jest taka, że na szerokim obrazie dodanie dwóch linii kodu (definicja zmiennej i instrukcja importu) do każdej klasy nie jest aż tak wielkim problemem. Zwłaszcza, że musisz tylko dodać je do klas, które zachowują się i dlatego musisz wykonać rejestrowanie. To powiedziawszy, konkretny wiersz kodu, którego używasz, jest podatny na błędy kopiowania i wklejania (więcej na ten temat później).
Ale ponieważ chcesz alternatywy, oto kilka z powodów, dla których możesz chcieć lub nie chcesz ich używać.
Użyj jednego rejestratora dla całej aplikacji
Jeśli nie obchodzi Cię, którą klasę zgłaszasz, lub chcesz umieścić w wiadomości cały niezbędny kontekst, wystarczy prosty rejestrator singletonów:
Moim zdaniem jedną z dużych zalet frameworka rejestrowania jest kontekst zapewniany przez osobne instancje rejestratora - choćby po to, aby kierować komunikaty dziennika do różnych miejsc docelowych. Nie zrezygnowałbym z tego tylko po to, aby zapisać jeden wiersz kodu (nadal potrzebujesz importu).
Dodatkowo zwiększa to gadatliwość w miejscu użycia, co skończy się znacznie większą liczbą naciśnięć klawiszy.
Utwórz swoje rejestratory w miejscu użytkowania
Wyrzucam to tylko dlatego, że eliminuje zmienną. Nie sądzę, żebym musiał to komentować. Chociaż pokazuje moją preferowaną technikę uzyskiwania instancji rejestratora.
Użyj postprocesora komponentu bean, aby wstrzyknąć program rejestrujący
W twoim przykładzie użyto Spring, a Spring pozwala ci podpiąć się do kodu inicjującego komponent bean. Możesz utworzyć postprocesor, który sprawdza komponent bean w poszukiwaniu
logger
zmiennej członka i tworzyLogger
instancję, gdy ją znajdzie.Chociaż taki postprocesor to zaledwie kilkadziesiąt wierszy kodu, to kolejna ruchoma część Twojej aplikacji, a zatem kolejne potencjalne źródło błędów. Wolę mieć ich jak najmniej.
Użyj mixin
Scala i Groovy zapewniają cechy , które pozwalają ci zakreślić zachowanie. Typowym wzorem Scali jest stworzenie
Logging
cechy, a następnie dodanie jej do klasy, która wymaga rejestrowania:Niestety oznacza to, że musisz zmieniać języki. O ile nie używasz Java 8, w takim przypadku możesz utworzyć
Logging
interfejs za pomocą „metody domyślnej”:Teraz, w ramach kodu klasy, możesz po prostu użyć
Jest to łatwe, ale ma kilka wad. Po pierwsze, zanieczyszcza interfejs każdej klasy, która go używa, ponieważ wszystkie metody interfejsu są publiczne. Być może nie jest tak źle, jeśli używasz go tylko dla klas, które są tworzone i wprowadzane przez Springa, szczególnie jeśli przestrzegasz rozdziału interfejs / implementacja.
Większy problem polega na tym, że musi sprawdzać rzeczywistą instancję rejestratora przy każdym połączeniu. Co jest szybkie, ale niepotrzebne.
Nadal potrzebujesz wyciągu z importu.
Przenieś program rejestrujący do nadklasy
Powtórzę: nie znajduję powtarzających się definicji rejestratora, ale jeśli tak, uważam, że to najlepsze podejście do ich eliminacji.
Teraz Twoje klasy kontrolerów dziedziczą
AbstractController
i mają dostęp dologger
zmiennej. Pamiętaj, że musisz umieścić@Controller
adnotację na konkretnej klasie.Niektórzy ludzie uznają to za wypaczenie dziedzictwa. Próbowałem je zmiękczyć, nazywając klasę,
AbstractController
a nieAbstractProjectClass
. Możesz sam zdecydować, czy istnieje związek typu „ czy to związek”.Inne osoby sprzeciwiają się użyciu zmiennej instancji zamiast zmiennej statycznej. Rejestratory statyczne IMO są podatne na błędy kopiuj-wklej, ponieważ musisz jawnie odwoływać się do nazwy klasy;
getClass()
zapewnia, że Twój rejestrator jest zawsze poprawny.źródło
MethodHandles.lookup().lookupClass()
jest lepsze niżObject.getClass()
?MethodHandles.lookup().lookupClass()
może być używany do zmiennych statycznych, nie jest podatny na błędy kopiowania i wklejania i jest szybki: stackoverflow.com/a/47112323/898747 Oznacza to dodatkowy inport, ale bardzo lubię moje rejestratory statyczne, więc warto przynajmniej wspomnieć :)Aby rozszerzyć odpowiedź dostarczoną przez @kdgregory, Groovy dostarcza
@Slf4j
(groovy.util.logging.Slf4j
) po wyjęciu z pudełka jako adnotację, która wykonuje transformację AST w klasie, aby przypiąć ją do loggera, który domyślnie przyjmuje nazwę zmiennej,log
jeśli nie zostanie określona.źródło