SLF4J: Alibaba je nametnuo korišćenje fasade dnevnika
Kada sam čitao izdanje Alibaba razvojnog priručnika za Songshan (ako nemate prijatelje, setite se da mi zatražite), otkrio sam jednu "prisilnu" regulaciju dnevnika:
U aplikaciji se ne sme direktno koristiti API sistem za evidenciju dnevnika (Log4j, Logback), već treba koristiti API okvira za evidenciju dnevnika, kao što je SLF4J, korišćenje okvira za evidenciju dnevnika uzorčaza fasade je pogodno za održavanje i ujedinjavanje načina evidencije dnevnika različitih klasa.
(Zašto sam ovaj tekst ručno otkucao? Zato što sam otkrio da Alibaba razvojni priručnik ima gramatičku grešku, pogledajte deo obeležen crveno ispod)

(Održavanje i ujedinjavanje, stavljanje ujedinjavanje na kraj je zaista neugodno za čitanje, malo nejasno "he" povezivanje, da li je urednik priručnika učitelj matematike učio jezik?)

Kada vidim ovu prisilnu regulaciju, ne mogu da se suzdržim od pitanja: "Zašto Alibaba razvojni priručnik prisiljava korišćenje SLF4J kao fasadu Log4j?" Šta se zapravo krije iza "neizrecivog" tajna?
(Prijatelji mogu sami da puste BGM CCTV 12 kanala)
PS: Uzput, pružam prijateljima malo znanja, Jakarta se pojavljuje u Alibaba razvojnom priručniku, u stvari je open source projekat pod Apache softverskom fondacijom. U stvari, Commons je ranije pripadao Jakarti, sada je kao zaseban projekat pod Apache, opis u Alibaba razvojnom priručniku više nije primeren, bilo bi pogodnije zameniti ga sa Apache Commons Logging.
(Opet sam pronašao grešku u Alibaba razvojnom priručniku, oprostite mi "nemilosrdan" radni stav)
01, Šta je SLF4J
SLF4J je skraćenica za Simple Logging Facade for Java (for≈4), to jest jednostavna fasada za evidenciju dnevnika, implementirana kroz obrazac fasade (Facade pattern, jedan od obrazaca dizajna, omogućuje višem interfejsu podsistema jedinstven viši-interfejs, čineći podsistem lakim za korišćenje), podržava java.util.logging, Log4J i Logback.
Autor SLF4J je takođe autor Log4J i Logback-a, njegova GitHub glavna stranica izgleda ovako:

Da li osećate hladnoću jesenje vetra? Može gigant ne želi da održava svoju GitHub glavnu stranicu? Moja GitHub glavna stranica je dovoljno tužna, nisam očekivao da je gigant još tužniji od mene, konačno mogu da se hvalim, "ja, Chenmo Wang Er, GitHub glavna stranica je zelenija od autora SLF4J, Log4J i Logback Ceki Gulcu-a......."

Početkom 1996. godine, evropski projekt bezbednosti elektronskog tržišta odlučio je da napiše svoj API za praćenje, konačno se ovaj API razvio u Log4j, već pri objavljivanju dobio je mnogo ljubavi.
U februaru 2002. godine, Sun je objavio sopstveni paket za evidenciju dnevnika java.util.logging (može se nazvati JUL), navodno je ideja implementacije koristila Log4j, jer je Log4j u to vreme već bio veoma zreo.
U avgustu 2002. godine, Apache je objavio sopstveni paket za evidenciju dnevnika, to jest JCL (Jakarta Commons Logging) pomenut u Alibaba razvojnom priručniku. JCL je imao velike ambicije, na osnovu JUL i Log4j pružao je sloj interfejsa abstrakcije, pogodno za korisnike da se prebacuju između JUL i Log4j.

Ali JCL nije bio toliko omiljen, neki su se žalili ovako:

Ceki Gulcu je takođe smatrao da JCL nije dobar, inače ne bi 2005. lično napisao novi projekat pod nazivom SLF4J, zar ne? Ali uvek treba platiti cenu za mešanje, SLF4J ima samo interfejse, nema implementaciju, ne može prisiliti Java i Apache da implementiraju SLF4J interfejse, zar ne? To je suviše teško, nerealno.
Ali razlog što se gigant zove gigant je taj što poseduje neverovatne sposobnosti koje obični ljudi nemaju, izgradio je tri mosta između SLF4J i JUL, Log4j, JCL:

Gigant je delovao, obučen i nahranjen, zar ne? Čak je i sopstveni Log4j izgradio most.
Suočeni sa snagom giganta, želim samo slabim glasom reći, "SLF4J ovaj fasadni zastavnik, misliš da je lako biti?"
02, Koji problem rešava SLF4J
U periodu zaraćenih država, svaka država je imala sopstvenu valutu, korišćenje tuđe valute nije bilo prikladno, zar ne? Tada pri trgovini je bilo teško, valute nisu bile ujedinjene, nije se moglo direktno trgovati, jer valute možda nisu bile ekvivalentne.
Kada je Qin Shi Huang ujedinio šest država, uveo je novu monetarnu politiku, cela zemlja koristi jednu valutu, tada su prethodni problemi rešeni.
Vidi, isti razlog, sistem evidencije dnevnika ima JUL, JCL, Ceki Gulcu je lično napisao 2 vrste, Log4j i Logback, svaki ima svoje prednosti i mane, dodatno korisnika hiljade, "obični ljudi imaju različite ukuse", što dovodi do toga da različite aplikacije mogu koristiti različite sisteme evidencije dnevnika.
Pretpostavimo da razvijamo sistem, planiramo da koristimo SLF4J kao fasadu, Log4j kao sistem evidencije dnevnika, u projektu koristimo A okvir, a fasada A okvira je JCL, sistem evidencije je JUL, to je ekvivalentno održavanju dva sistema evidencije dnevnika, zar ne?

Ovo je neugodno!
Ceki Gulcu je razmišljao o ovom problemu i rešio ga za nas! Pogledajmo rešenje koje nudi SLF4J zvanični sajt.

- Zamenite commons-logging.jar sa jcl-over-slf4j.jar
- Uvedite jul-to-slf4j.jar
Da bismo simulirali ovaj proces, napravićemo projekat koji koristi JCL.
Prvi korak, uvedite commons-logging.jar u datoteku pom.xml:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>Drugi korak, kreirajte testnu klasu:
package com.itwanger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author WeChat pretraži "Chenmo Wang Er", odgovori sa ključnom rečju PDF
*/
public class Demo {
private static Log logger = LogFactory.getLog(Demo.class);
public static void main(String[] args) {
logger.info("jcl");
}
}Ova klasa će dobiti Log objekat putem LogFactory i koristiti metod info() da ispiše red dnevnika.
Prilikom otklanjanja grešaka ovog koda možete videti, Log implementacija ima četiri vrste:

Ako se ne veže Log4j, podrazumevano će se izabrati Jdk14Logger——Logger objekat koji vraća, je upravo java.util.logging.Logger, to jest JUL.
Stoga, možete videti sledeće informacije na konzoli:
21. oktobar 2020. 15:13:30 com.itwanger.Demo main
informacije: jclKako transformisati projekat koji koristi JCL u projekat koji koristi SLF4J?
Treći korak, zamenite commons-logging.jar sa jcl-over-slf4j.jar, i dodajte jul-to-slf4j.jar, slf4j-log4j12.jar (automatski će uvesti slf4j-api.jar i log4j.jar):
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.29</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>Četvrti korak, kreirajte datoteku log4j.properties u direktorijumu resources, sadržaj je sledeći:
### Podešavanje###
log4j.rootLogger = debug,stdout,D
### Izlaz informacija na konzolu ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### Izlaz dnevnika DEBUG nivoa i više u =debug.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.D.File = debug.log
log4j.D.Append = true
log4j.D.Threshold = DEBUG
log4j.D.layout = org.apache.log4j.PatternLayout
log4j.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%nPonovo pokrenite Demo klasu, možete videti da će se u direktorijumu target generisati datoteka pod nazivom debug.log, sadržaj je sledeći:
2020-10-21 15:32:06 [ main:0 ] - [ INFO ] jclI možete videti sledeće informacije na konzoli:
[INFO ] 2020-10-21 15:32:06,192 method:com.itwanger.Demo.main(Demo.java:12)
jclPažljivo upoređujući, možete videti da se ovaj put format izlaza razlikuje od prethodnog, to je zato što formati dnevnika Log4j i JUL nisu isti.
Dodatno, jeste li primetili? Nismo promenili Demo testnu klasu, ona još uvek koristi JCL način dobijanja Log-a:
private static Log logger = LogFactory.getLog(Demo.class);Ali format izlaza je već prešao na Log4j!
SLF4J pored ovog rešenja, nudi i rešenje za vezivanje Logback zamenu JUL, JCL, Log4j:

I rešenje za vezivanje JUL zamenu JCL i Log4j:

Previše moćno, zar ne? Ako da, molim vas da upišete 666 u sekciji za komentare.

03, Gde je SLF4J jači od Log4J
SLF4J pored rešavanja gore navedenih problema, pomaže našim aplikacijama da budu nezavisne od bilo kojeg specifičnog sistema evidencije dnevnika, ima i vrlo moćnu funkciju, to je što SLF4J koristi zamenljivu {} prilikom štampanja dnevnika, malo liči na metod format() klase String (koristi %s i druge za popunjavanje parametara), ali je pogodnije, što u velikoj meri poboljšava performanse programa.
Kao i poznato, stringovi su nepromenjivi, spajanje stringova će stvoriti mnoge nepotrebne string objekte, koje ekstremno troše memorijski prostor. Ali Log4J prilikom štampanja dnevnika sa parametrima može samo koristiti način spajanja stringova:
String name = "Chenmo Wang Er";
int age = 18;
logger.debug(name + ",godina:" + age + ",je vrlo bezobrazan programer");Vrlo teško, ali nakon dodavanja SLF4J, ovaj problem je lako rešen. Pogledajmo detaljne korake dodavanja SLF4J u projekat Log4j.
Prvi korak, zamenite log4j zavisnost sa slf4j-log4j12 (Maven će automatski uvesti slf4j-api.jar i log4j.jar):
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>Drugi korak, kreirajte datoteku log4j.properties u direktorijumu resources, sadržaj je potpuno isti kao u Log4j članku:
### Podešavanje###
log4j.rootLogger = debug,stdout,D,E
### Izlaz informacija na konzolu ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### Izlaz dnevnika DEBUG nivoa i više u =debug.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.D.File = debug.log
log4j.D.Append = true
log4j.D.Threshold = DEBUG
log4j.D.layout = org.apache.log4j.PatternLayout
log4j.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### Izlaz dnevnika ERROR nivoa i više u =error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.E.File =error.log
log4j.E.Append = true
log4j.E.Threshold = ERROR
log4j.E.layout = org.apache.log4j.PatternLayout
log4j.E.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%nTreći korak, kreirajte testnu klasu:
package com.itwanger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author WeChat pretraži "Chenmo Wang Er", odgovori sa ključnom rečju PDF
*/
public class Log4jSLF4JDemo {
private static final Logger logger = LoggerFactory.getLogger(Log4jSLF4JDemo.class);
public static void main(String[] args) {
logger.debug("{},je vrlo bezobrazan programer","Chenmo Wang Er");
}
}Vidite, korišćenje zamenljivih je mnogo pogodnije nego "+" operator. I u ovom trenutku nije potrebno isDebugEnabled() prvo proceniti, metod debug() će se izvršiti pre spajanja stringova.

Ako je samo Log4J, prvo će se izvršiti spajanje stringova, zatim metod debug(), pogledajmo primer koda:
String name = "Chenmo Wang Er";
int age = 18;
logger.debug(name + ",godina:" + age + ",je vrlo bezobrazan programer");Prilikom otklanjanja grešaka ovog koda možete videti, kao što je prikazano donjoj slici:

To znači, ako sistem evidencije dnevnika nije DEBUG nivoa, dodatno će se izvršiti operacija spajanja stringova, uzalud će se potrošiti performanse.
Obratite pažnju, u Alibaba razvojnom priručniku postoji još jedna "prisilna" regulacija:

To je zato što ako je parametar osnovni tip podataka, prvo će se izvršiti automatski boksiranje (Integer.valueOf()). Testni kod je sledeći:
logger.debug("Chenmo Wang Er, {}godina", 18);Kroz alat za dekompilaciju može se videti:
logger.debug("Chenmo Wang Er, {}godina", Integer.valueOf(18));Ako parametar zahteva pozivanje drugih metoda, metod debug() će kasnije pozvati.

To jest, ako ne isDebugEnabled(), u slučaju da nije DEBUG nivo, dodatno će se izvršiti operacije automatskog boksiranja i pozivanja drugih metoda — performanse programa će pasti!
Rezultat pokretanja testne klase je isti kao prethodni Log4J, prijatelji mogu kliknuti na link da idu na Log4j članak za poređenje.
04, Zaključak
Jednostavno sumirajmo ovaj članak.
Prilikom korišćenja sistema evidencije dnevnika, morate koristiti SLF4J kao fasadu.
SLF4J može ujediniti sistem evidencije dnevnika, kao viši sloj apstraktnog interfejsa, ne treba brinuti o implementaciji nižeg nivoa evidencije dnevnika, može biti Log4j, takođe može biti Logback, ili JUL, JCL.
SLF4J može koristiti zamenljive prilikom štampanja dnevnika, što ne samo poboljšava performanse programa (smanjenje privremenih stringova, manji posao garbage collector-a), već čini kod estetskim i ujedinjenim.
Ako prijatelji znaju više tajni, predlažem da ostavite u sekciji za komentare.
