UWAGA: Zaleca wszystko zalogowaniu Kod zostać przeniesione do korzystania SLF4J (zwłaszcza log4j 1.x). Chroni Cię przed utknięciem w jakimkolwiek typie problemów (np. Błędów) w określonych implementacjach rejestrowania. Nie tylko "naprawia" dobrze znane problemy z implementacją backendu, ale także działa z nowszymi, szybszymi implementacjami, które pojawiły się na przestrzeni lat.
W bezpośredniej odpowiedzi na swoje pytanie, o co to będzie wyglądać przy użyciu SLF4J:
LOGGER.debug("some texts {} with patterns {}", object1, object2);
Najważniejszą nieco od tego, co podałeś jest fakt, trzeba przejechać dwie instancje obiektu. Metody object1.toString()
i object2.toString()
nie są natychmiast analizowane. Co ważniejsze, metody toString()
są oceniane tylko wtedy, gdy dane, które zwrócą, będą faktycznie używane; tj. prawdziwe znaczenie leniwej oceny.
Próbowałem wymyślić bardziej ogólny wzór, który mógłbym użyć, który nie wymagałby mojego przesłonięcia toString()
w tonach klas (i są klasy, w których nie mam dostępu do nadpisania). Wymyśliłem proste rozwiązanie typu "drop-in-place". Ponownie, używając SLF4J, komponuję ciąg znaków tylko wtedy, gdy/logowanie dla poziomu jest włączone. Oto mój kod:
class SimpleSfl4jLazyStringEvaluation {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleSfl4jLazyStringEvaluation.class);
...
public void someCodeSomewhereInTheClass() {
//all the code between here
LOGGER.debug(
"{}"
, new Object() {
@Override
public String toString() {
return "someExpensiveInternalState=" + getSomeExpensiveInternalState();
}
}
//and here can be turned into a one liner
);
}
private String getSomeExpensiveInternalState() {
//do expensive string generation/concatenation here
}
}
I uprościć do jedno-liner, można skrócić linię Logger w someCodeSomewhereInTheClass(), aby być:
LOGGER.debug("{}", new Object(){@Override public String toString(){return "someExpensiveInternalState=" + getSomeExpensiveInternalState();}});
Mam teraz refactored cały mój kod logowania podążać za tym prostym modelem. To znacznie uprościło sprawę. A teraz, gdy widzę jakikolwiek kod logowania, który tego nie używa, zmieniam kod logowania, aby użyć tego nowego wzorca, nawet jeśli jest on jeszcze potrzebny. W ten sposób, jeśli/kiedy wprowadzona zostanie później zmiana, wymagająca dodania jakiejś "kosztownej" operacji, to element infrastruktury jest już w tym miejscu, co upraszcza zadanie polegające na dodaniu operacji.
Nowsze wersje Log4J pozwalają na zastępowanie parametrów, patrz http://stackoverflow.com/a/14078904/620113 – computermacgyver
Czy to faktycznie działa - to sformatuje ciąg, ale czy robi to "leniwe"? Zrobiłem mały test, w którym argumenty lazyFormat są wywołaniami funkcji, która drukuje do System.err i wydawało się, że argumenty w Object ... o zostaną ocenione, nawet jeśli String.format (s, o) nie jest. – OneSolitaryNoob
OneSolitaryNoob - To nie robi leniwe rzeczy. Dostawca odpowiedzi wskazuje, że można to zrobić za pomocą metody "isDebugEnabled()" w metodzie toString(). W mojej odpowiedzi dostarczyłem bardziej ogólny, leniwy wzorzec logowania: http://stackoverflow.com/a/18317629/501113 – chaotic3quilibrium