SLF4J adalah lapisan abstraksi kerangka log, yang mengikat kerangka log spesifik, seperti log4j, logback, java logging API, dll. SLF4J juga memiliki implementasi default sendiri, tetapi kami masih menggunakan SLF4J sebagai lapisan abstraksi dari kerangka log.
Untuk menggunakan slf4j, Anda harus menyertakan ketergantungan pada "org.slf4j: slf4j-api".
Ulasan sederhana dari pola fasad
SLF4J adalah aplikasi khas mode fasad, jadi sebelum berbicara tentang SLF4J, mari kita tinjau mode fasad secara singkat.
Mode fasad, yang intinya adalah bahwa komunikasi dengan subsistem harus dilakukan melalui objek penampilan terpadu, membuat subsistem lebih mudah digunakan. Struktur pola etalase digunakan untuk mewakili gambar:
Inti dari mode fasad adalah fasad, yaitu objek fasad, dan inti dari objek fasad adalah beberapa poin:
Secara umum, hanya meninjau mode toko sudah cukup di sini, dan Anda akan mulai belajar tentang SLF4J berikutnya.
Mengapa kita menggunakan slf4j
Mengapa kita menggunakan slf4j? Misalnya:
Kami menggunakan logback di sistem kami sendiri
Sistem kami menggunakan A.Jar, dan sistem log yang digunakan di A.Jar adalah log4j
Sistem kami menggunakan B.Jar lagi, dan sistem log yang digunakan di B.Jar adalah Slf4j-Simple
Dengan cara ini, sistem kami harus mendukung dan memelihara tiga kerangka kerja log: Logback, Log4J, dan Slf4j-Simple pada saat yang sama, yang sangat tidak nyaman.
Cara untuk menyelesaikan masalah ini adalah dengan memperkenalkan lapisan adaptasi, yang menentukan sistem log mana yang akan digunakan, dan penelepon hanya perlu dilakukan adalah mencetak log tanpa peduli tentang cara mencetak log. Slf4j atau Commons-logging adalah lapisan adaptasi ini, dan Slf4j adalah objek dari penelitian ini.
Dari deskripsi di atas, kita harus mengetahui satu hal dengan jelas: SLF4J hanyalah standar logging, bukan implementasi spesifik dari sistem logging. Sangat penting untuk memahami kalimat ini. Slf4j hanya menyebutkan dua hal:
SLF4J-Simple dan Logback keduanya merupakan implementasi spesifik dari SLF4J. Log4j tidak secara langsung mengimplementasikan SLF4J, tetapi ada jembatan lapisan pertama SLF4J-LOG4J12 khusus untuk mengimplementasikan SLF4J.
Untuk lebih memahami SLF4J, pertama -tama kami melihat contoh -contohnya dan kemudian membaca kode sumber. Saya percaya pembaca akan memiliki pemahaman yang lebih dalam tentang SLF4J.
Contoh aplikasi SLF4J
Seperti disebutkan di atas, implementasi langsung/tidak langsung dari SLF4J termasuk SLF4J-Simple, Logback, SLF4J-LOG4J12. Pertama -tama mari kita tentukan pom.xml dan perkenalkan paket JAR yang relevan:
<!-Teks Asli: Cangjie di Mei http://www.cnblogs.com/xrq730/p/8619156.html-> <proyek xmlns = "http://maven.apache.org/pom/4.0.0" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" xsi: schemalocation = "http://maven.apache.org/pom/4.0.0 http://maven.apache.org.org/xd/. ".0 <ModelVersion> 4.0.0 </ModelVersion> <GroupId> org.xrq.log </groupid> <ArTifactId> log-test </artifactid> <version> 1.0.0 </version> <packaging> Jar </packaging> <name> </name> <rerl> <rurl> http:/maven.ape. </nameo </name> <url> http:/maven.apache.apache. <Project.build.sourceencoding> UTF-8 </project.build.sourceencoding> </properties> <dependencies> <dependency> <groupid> JUNIT </groupid> <ArTifactId> Junit </Artifactid> <version> 4.11 </Versi </SCOPED> </scope </artifactid> <version> 4.11 </versi> <scope> </scope> </scope </version> </Versi> </Versi> </scope> </Scope> </Versi> </Version> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <dependency> <GroupId> org.slf4j </groupid> <ArTifactId> slf4j-simple </artifactid> <version> 1.7.25 </version> </dependency> <dependency> <groupid> LOG4J </groupid> <ArTifactId> LOG4J </ArtifactId> Versi 1.2.17 </grupid> <ArTifacTID> </artifactid> </Versi </Groupid> <T/ArtifactId </ArtifactId </ArtifactId </ArtifactId </ArtifactId </ArtifactID> </Artifactid <GroupId> org.slf4j </groupid> <ArTifactId> slf4j-log4j12 </arttifactid> <version> 1.7.21 </versi
Tulis kode Java sederhana:
@Testpublic void testslf4j () {logger logger = loggerFactory.getLogger (objek.class); Logger.Error ("123"); }Selanjutnya, pertama -tama kami mengomentari baris 30 hingga 49 dari pom.xml di atas, yaitu, kami tidak memperkenalkan kelas implementasi SLF4J dan menjalankan metode pengujian. Mari kita lihat output konsol sebagai:
Melihat output tanpa log, ini memverifikasi pandangan kami: SLF4J tidak memberikan implementasi log spesifik, dan hanya SLF4J yang tidak dapat mencetak log.
Kemudian buka anotasi logback-klasik dan jalankan metode pengujian. Mari kita lihat output konsol sebagai:
Saya melihat bahwa kita hanya perlu memperkenalkan kelas implementasi spesifik SLF4J, dan kita dapat menggunakan kerangka log untuk mengeluarkan log.
Akhirnya, kami melakukan tes. Kami membuka semua log, memperkenalkan Logback-Classic, Slf4j-Simple, Log4j, Jalankan Metode Uji, dan output konsolnya adalah:
Perbedaan dari hal di atas adalah bahwa Anda dapat mengoutput log, tetapi beberapa log alarm akan menjadi output, mendorong kami untuk memperkenalkan beberapa implementasi SLF4J pada saat yang sama, dan kemudian memilih salah satunya sebagai sistem log yang kami gunakan.
Dari contohnya, kita dapat menarik kesimpulan penting, yaitu, peran SLF4J: selama semua kode menggunakan objek fasad SLF4J, kita tidak perlu peduli dengan implementasinya yang spesifik. Pada akhirnya, satu implementasi spesifik dapat digunakan di semua tempat, dan penggantian dan pemeliharaan sangat nyaman.
Prinsip Implementasi SLF4J
Saya telah melihat contoh SLF4J di atas, dan saya akan mempelajari implementasi SLF4J di bawah ini. Kami hanya akan fokus pada kode kunci.
Penggunaan SLF4J adalah kalimat yang tetap tidak berubah sepanjang tahun, "Logger Logger = LoggerFactory.getLogger (Object.class);", yang menunjukkan bahwa ini adalah menggunakan LoggerFactory untuk mendapatkan implementasi spesifik dari antarmuka logger yang disediakan oleh SLF4J. Metode GetLogger dari LoggerFactory diimplementasikan sebagai:
public static Logger getLogger (class <?> clazz) {logger logger = getLogger (clazz.getName ()); if (detect_logger_name_mishatch) {class <?> AutoComputedCallingClass = util.getCallingClass (); if (AutoComputedCallingClass! = null && nonmatchingclasses (clazz, autocomputedcallingclass)) {util.report (string.format ("Detected Logger Name Mismatch. NAMA yang Diberi:"%s /"; nama yang dihitung: /"%s /".", Logger.get); Util.report ("lihat" + logger_name_mishatch_url + "untuk penjelasan"); }} return logger;}Mulailah dengan kode dari baris 2 dan ikuti metode Bind () ke LoggerFactory:
private final static void bind () {coba {set <rerl> staticloggerbinderpathset = null; // Skip Check di bawah Android, lihat juga // http://jira.qos.ch/browse/slf4j-328 if (! isAndroid ()) {staticloggerBinderPathset = findPossiblestaticLoggerbinderPathset (); Reportmultiplebindingambiguity (StaticLoggerbinderPathset); } // Baris berikutnya melakukan pengikat staticloggerbinder.getsingleton (); Inisialisasi_state = sukses_initialisasi; ReportActualBinding (StaticLoggerbinderPathset); fixsubstituteloggers (); replayevents (); // Lepaskan semua sumber daya di subst_factory subst_factory.clear (); } catch (noClassDeffoundError ncde) {string msg = ncde.getMessage (); if (MessageContainSorgslf4JImplSticLogGerbinder (msg)) {initialization_state = nop_fallback_initialization; Util.report ("Gagal memuat kelas /"org.slf4j.impl.staticloggerbinder/". "); Util.report ("Default ke Implementasi Logger No-Operation (NOP)"); Util.report ("lihat" + no_staticloggerbinder_url + "untuk rincian lebih lanjut."); } else {failbinding (ncde); Lempar NCDE; }} catch (java.lang.nosuchmethoderror nsme) {string msg = nsme.getMessage (); if (msg! = null && msg.contains ("org.slf4j.impl.staticloggerbinder.getsingleton ()")) {initialization_state = failure_initialization; Util.report ("Slf4j-API 1.6.x (atau lebih baru) tidak sesuai dengan pengikatan ini."); Util.report ("Ikatan Anda adalah versi 1.5.5 atau lebih awal."); Util.report ("Tingkatkan ikatan Anda ke versi 1.6.x."); } lempar nsme; } catch (Exception e) {fagedbinding (e); Lemparkan IlegalStateException baru ("Kegagalan Inisialisasi yang Tidak Terduga", E); }}Baris 7 dari tempat ini adalah kunci, lihat kode:
set statis <rerl> findPossiblestaticLoggerBinderPathset () {// Gunakan set alih -alih daftar untuk menangani bug #138 // LinkedHashSet sesuai di sini karena mempertahankan pesanan penyisipan // selama iterasi set <rerl> staticloggerBinderPathset = new LinkedHashset <url> (); Coba {ClassLoader LoggerFactoryClassLoader = LoggerFactory.class.getClassLoader (); Enumeration <rerl> jalur; if (loggerFactoryClassLoader == null) {paths = classloader.getSystemResources (static_logger_binder_path); } else {paths = LoggerFactoryClassLoader.getResources (static_logger_binder_path); } while (paths.hasmoreElements ()) {url path = paths.nextElement (); staticloggerbinderpathset.add (path); }} catch (ioException IOE) {util.report ("Kesalahan mendapatkan sumber daya dari path", ioe); } return staticloggerbinderpathset;}Titik kunci dari tempat ini sebenarnya adalah kode pada baris 12. Saat mendapatkanLogger, Anda akan pergi ke ClassPath untuk menemukan static_logger_binder_path. Nilai static_logger_binder_path adalah "org/slf4j/impl/staticloggerbinder.class", yaitu, semua implementasi slf4j, di bawah jalur paket jar yang disediakan, harus ada "org/slf4j/impl/staticloggerBinder.class". Kita bisa melihat:
Kami tidak dapat menghindari memperkenalkan beberapa implementasi SLF4J dalam sistem pada saat yang sama, sehingga tempat penerima adalah satu set. Anda harus mencatat bahwa akan ada peringatan ketika bagian di atas memperkenalkan logback, slf4j-simple, dan log4j pada saat yang sama dengan demonstrasi:
Ini karena ada tiga "org/slf4j/impl/staticloggerbinder.class" yang ada. Pada saat ini, laporan output Metode Konsol ReportmultiPlebindingambiguity:
private static void Reportmultiplebindingambiguity (set <RURL> bindPathset) {if (isambiguousstaticLoggerbindindindePathset (binderpathset)) {util.report ("jalur kelas berisi beberapa ikatan slf4j."); untuk (jalur url: bindPathset) {util.report ("Ditemukan ikatan di [" + path + "]"); } Util.report ("lihat" + multiple_bindings_url + "untuk penjelasan."); }}Kemudian netizen mungkin bertanya, apa yang harus saya lakukan jika ada tiga "org/slf4j/impl/staticloggerbinder.class" pada saat yang sama? Pertama -tama, ditentukan bahwa ini tidak akan menyebabkan kesalahan dalam startup, dan kedua, selama kompilasi, kompiler akan memilih salah satu staticloggerbinder.class untuk mengikat.
Akhirnya, StaticLoggerbinder relatif sederhana. StaticloggerBinders yang berbeda memiliki implementasi getLoggerFactory yang berbeda. Setelah mendapatkan IloggerFactory, hubungi GetLogger dan dapatkan logger spesifik. Anda dapat menggunakan Logger untuk output log.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.