SLF4J เป็นเลเยอร์ Abstraction Log Framework ซึ่งเชื่อมโยงเฟรมเวิร์กบันทึกเฉพาะเช่น log4j, logback, Java Logging API ฯลฯ SLF4J ยังมีการใช้งานเริ่มต้นของตัวเอง แต่เรายังคงใช้ SLF4J เป็นชั้นที่เป็นนามธรรม
ในการใช้ SLF4J คุณต้องรวมถึงการพึ่งพา "org.slf4j: SLF4J-API"
รีวิวง่ายๆเกี่ยวกับรูปแบบของอาคาร
SLF4J เป็นแอปพลิเคชั่นทั่วไปของโหมดซุ้มดังนั้นก่อนที่จะพูดคุยเกี่ยวกับ SLF4J ลองทบทวนโหมดด้านหน้าสั้น ๆ
โหมดซุ้มซึ่งมีหลักการคือการสื่อสารกับระบบย่อยจะต้องดำเนินการผ่านวัตถุที่ปรากฏเป็นหนึ่งเดียวทำให้ระบบย่อยใช้งานง่ายขึ้น โครงสร้างของรูปแบบหน้าร้านใช้เพื่อแสดงภาพ:
แกนกลางของโหมดซุปซองคือซุ้มนั่นคือวัตถุด้านหน้าและแกนกลางของวัตถุด้านหน้าคือหลายจุด:
โดยทั่วไปเพียงแค่ตรวจสอบโหมดร้านค้าก็เพียงพอแล้วและคุณจะเริ่มเรียนรู้เกี่ยวกับ SLF4J ต่อไป
ทำไมเราถึงใช้ SLF4J
ทำไมเราถึงใช้ SLF4J? ตัวอย่างเช่น:
เราใช้ logback ในระบบของเราเอง
ระบบของเราใช้ A.JAR และระบบบันทึกที่ใช้ใน A.JAR คือ log4j
ระบบของเราใช้ b.jar อีกครั้งและระบบบันทึกที่ใช้ใน b.jar คือ slf4j-simple
ด้วยวิธีนี้ระบบของเราจะต้องสนับสนุนและบำรุงรักษาสามกรอบบันทึก: logback, log4j และ slf4j-simple ในเวลาเดียวกันซึ่งไม่สะดวกมาก
วิธีการแก้ปัญหานี้คือการแนะนำเลเยอร์การปรับตัวซึ่งกำหนดระบบบันทึกที่จะใช้และผู้โทรต้องทำเพียงแค่พิมพ์บันทึกโดยไม่สนใจวิธีการพิมพ์บันทึก SLF4J หรือการบันทึกคอมมอนส์คือเลเยอร์การปรับตัวนี้และ SLF4J เป็นเป้าหมายของการวิจัยบทความนี้
จากคำอธิบายข้างต้นเราต้องรู้สิ่งหนึ่งอย่างชัดเจน: SLF4J เป็นเพียงมาตรฐานการบันทึกไม่ใช่การใช้งานระบบการบันทึกเฉพาะ เป็นเรื่องสำคัญมากที่จะต้องเข้าใจประโยคนี้ SLF4J กล่าวถึงการทำสองสิ่งเท่านั้น:
SLF4J-Simple และ Logback เป็นทั้งการใช้งานเฉพาะของ SLF4J log4j ไม่ได้ใช้ SLF4J โดยตรง แต่มีสะพานชั้นแรกสุดพิเศษ SLF4J-LOG4J12 เพื่อใช้ SLF4J
เพื่อให้เข้าใจ SLF4J ได้ดีขึ้นก่อนอื่นเราจะดูตัวอย่างก่อนจากนั้นอ่านซอร์สโค้ด ฉันเชื่อว่าผู้อ่านจะมีความเข้าใจอย่างลึกซึ้งเกี่ยวกับ SLF4J
ตัวอย่างแอปพลิเคชัน SLF4J
ดังที่ได้กล่าวมาแล้วการใช้งานโดยตรง/โดยอ้อมของ SLF4J รวมถึง SLF4J-Simple, Logback, SLF4J-Log4J12 ก่อนอื่นกำหนด pom.xml และแนะนำแพ็คเกจ jar ที่เกี่ยวข้อง:
<!-ข้อความต้นฉบับ: Cangjie ในเดือนพฤษภาคม http://www.cnblogs.com/xrq730/p/8619156.html-> <project xmlns = "http://maven.apache.org/pom/4.0.0.0" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" xsi: schemalocation = "http://maven.apache.org/pom/4.0.0 http://maven.apache.apache.org/xsd.org <SoderVersion> 4.0.0 </StorVersion> <roupID> org.xrq.log </groupId> <ratifactid> บันทึกการทดสอบ </artifactid> <erson> 1.0.0 </Sersion> <packaging> jar </packaging> <name> บันทึกการทดสอบ </name> <Project.build.sourceencoding> UTF-8 </project.build.sourceencoding> </premerties> <perctencies> <predency> <sdercterency> <sdercter> <RoupID> org.slf4j </groupid> <ratifactid> slf4j-api </artifactid> <persion> 1.7.25 </version> </การพึ่งพา> <pendency> <roupid> ch.qos.logback </GroupId> <RoupID> org.slf4j </groupId> <ratifactId> slf4j-simple </artifactiD> <version> 1.7.25 </เวอร์ชัน> </การพึ่งพา> <การพึ่งพา <RoupID> org.slf4j </groupId> <ratifactId> SLF4J-LOG4J12 </artifactId> <version> 1.7.21 </เวอร์ชัน> </derctency> </pendencies>
เขียนรหัส Java อย่างง่าย:
@TestPublic Void Testslf4j () {logger logger = loggerFactory.getLogger (Object.class); logger.error ("123"); -ต่อไปเราจะแสดงความคิดเห็นก่อนบรรทัดที่ 30 ถึง 49 ของ POM.XML ด้านบนนั่นคือเราไม่แนะนำคลาสการใช้งาน SLF4J ใด ๆ และเรียกใช้วิธีการทดสอบ มาดูผลลัพธ์ของคอนโซลเป็น:
เมื่อเห็นผลลัพธ์ที่ไม่มีบันทึกใด ๆ สิ่งนี้จะตรวจสอบมุมมองของเรา: SLF4J ไม่ได้ให้การใช้งานบันทึกเฉพาะและ SLF4J เท่านั้นที่ไม่สามารถพิมพ์บันทึกได้
จากนั้นเปิดคำอธิบายประกอบ logback-classic และเรียกใช้วิธีการทดสอบ มาดูผลลัพธ์ของคอนโซลเป็น:
ฉันเห็นว่าเราเพียงแค่ต้องแนะนำคลาสการใช้งานเฉพาะของ SLF4J และเราสามารถใช้ Framework บันทึกเพื่อส่งออกบันทึก
ในที่สุดเราทำการทดสอบ เราเปิดบันทึกทั้งหมดแนะนำ logback-classic, SLF4J-Simple, log4j, เรียกใช้วิธีการทดสอบและเอาต์พุตคอนโซลคือ:
ความแตกต่างจากข้างต้นคือคุณสามารถส่งออกบันทึก แต่บันทึกการเตือนภัยบางอย่างจะถูกส่งออกแจ้งให้เราแนะนำการใช้งาน SLF4J หลายครั้งในเวลาเดียวกันจากนั้นเลือกหนึ่งในนั้นเป็นระบบบันทึกที่เราใช้
จากตัวอย่างเราสามารถวาดข้อสรุปที่สำคัญนั่นคือบทบาทของ SLF4J: ตราบใดที่รหัสทั้งหมดใช้วัตถุซุปเปอร์ SLF4J เราไม่จำเป็นต้องใส่ใจเกี่ยวกับการใช้งานที่เฉพาะเจาะจง ในท้ายที่สุดการใช้งานที่เฉพาะเจาะจงหนึ่งสามารถใช้ในทุกสถานที่และการเปลี่ยนและการบำรุงรักษานั้นสะดวกมาก
หลักการการใช้งาน SLF4J
ฉันได้ดูตัวอย่าง SLF4J ด้านบนและฉันจะศึกษาการใช้งาน SLF4J ด้านล่าง เราจะมุ่งเน้นไปที่รหัสคีย์เท่านั้น
การใช้ SLF4J เป็นประโยคที่ยังคงไม่เปลี่ยนแปลงตลอดทั้งปี "Logger logger = loggerFactory.getLogger (Object.class);" ซึ่งแสดงให้เห็นว่านี่คือการใช้ LoggerFactory เพื่อรับการใช้งานเฉพาะของอินเทอร์เฟซ logger ที่จัดทำโดย SLF4J วิธีการ getLogger ของ loggerFactory ถูกนำมาใช้เป็น:
Public Static Logger GetLogger (คลาส <?> Clazz) {logger logger = getLogger (clazz.getName ()); if (detect_logger_name_mismatch) {คลาส <?> autocomputedCallingClass = util.getCallingClass (); if (AutoComputedCallingClass! = null && nonmatchingClasses (clazz, autocomputedCallingClass)) {util.Report (String.format ("ตรวจพบชื่อ Logger ไม่ตรงกันชื่อที่กำหนด: /"%s /"; util.Report ("ดู" + logger_name_mismatch_url + "สำหรับคำอธิบาย"); }} return logger;}เริ่มต้นด้วยรหัสจากบรรทัดที่ 2 และทำตามวิธีการ bind () เพื่อ loggerFactory:
โมฆะคงที่ครั้งสุดท้ายส่วนตัว bind () {ลอง {set <url> staticLoggerBinderPathset = null; // ข้ามเช็คภายใต้ Android ดูเพิ่มเติม // http://jira.qos.ch/browse/slf4j-328 ถ้า (! isandroid ()) {staticloggerBinderPathset = findPossiblestaticLoggerBinderPathset (); ReportMultipleBindingambiguity (StaticLoggerBinderPathset); } // บรรทัดถัดไปทำ binding staticloggerbinder.getsingleton (); Initialization_state = success_initialization; reportactualbinding (StaticLoggerBinderPathset); fixsubstituteloggers (); replayEvents (); // ปล่อยทรัพยากรทั้งหมดใน subst_factory substory.clear (); } catch (noclassDeffoundError ncde) {string msg = ncde.getMessage (); if (messageContainsorgslf4jimplstaticloggerbinder (msg)) {imitricization_state = nop_fallback_initialization; util.Report ("ไม่สามารถโหลดคลาส /"org.slf4j.impl.staticloggerbinder/". "); util.Report ("การผิดนัดให้กับการใช้งาน Logger No-Operation (NOP)"); util.Report ("ดู" + no_staticloggerbinder_url + "สำหรับรายละเอียดเพิ่มเติม"); } else {faildbinding (ncde); โยน ncde; }} catch (java.lang.nosuchmethoderror nsme) {สตริง msg = nsme.getMessage (); if (msg! = null && msg.contains ("org.slf4j.impl.staticloggerbinder.getsingleton ()")) {imitialization_state = failed_initialization; util.Report ("SLF4J-API 1.6.x (หรือใหม่กว่า) ไม่เข้ากันกับการผูกมัดนี้"); util.Report ("การผูกของคุณคือเวอร์ชัน 1.5.5 หรือก่อนหน้านี้"); util.Report ("อัปเกรดการเชื่อมโยงเป็นเวอร์ชัน 1.6.x. "); } โยน nsme; } catch (exception e) {failedbinding (e); โยนใหม่ unlislStateException ("ความล้มเหลวในการเริ่มต้นที่ไม่คาดคิด", e); -บรรทัดที่ 7 ของสถานที่นี้เป็นคีย์ดูที่รหัส:
ชุดคงที่ <url> findpossiblestaticloggerbinderpathset () {// ใช้ชุดแทนที่จะเป็นรายการเพื่อจัดการกับข้อผิดพลาด #138 // linkedhashset เหมาะสมที่นี่เพราะมันรักษาคำสั่งแทรก // ในระหว่างการทำซ้ำชุด <url> StaticLoggerBinderPathset = ใหม่ ลอง {classloader loggerFactoryClassLoader = loggerFactory.class.getClassLoader (); การแจงนับ <url> เส้นทาง; if (loggerFactoryClassLoader == null) {paths = classloader.getSystemResources (static_logger_binder_path); } else {paths = loggerFactoryClassLoader.getResources (static_logger_binder_path); } ในขณะที่ (paths.hasmoreElements ()) {url path = paths.nextelement (); staticloggerbinderpathset.add (เส้นทาง); }} catch (ioexception ioe) {util.Report ("ข้อผิดพลาดรับทรัพยากรจากเส้นทาง", ioE); } return staticloggerBinderPathset;}จุดสำคัญของสถานที่นี้คือรหัสในบรรทัดที่ 12 เมื่อรับล็อกเกอร์คุณจะไปที่คลาสท. เพื่อค้นหา static_logger_binder_path ค่า static_logger_binder_path คือ "org/slf4j/impl/staticloggerbinder.class" นั่นคือการใช้งาน SLF4J ทั้งหมดภายใต้เส้นทางแพ็คเกจ JAR ที่ให้ไว้จะต้องมี "org/slf4j/impl/staticloggerbinder.class" เราสามารถดู:
เราไม่สามารถหลีกเลี่ยงการแนะนำการใช้งาน SLF4J หลายครั้งในระบบในเวลาเดียวกันดังนั้นสถานที่รับคือชุด คุณควรทราบว่าจะมีคำเตือนเมื่อส่วนข้างต้นแนะนำ logback, slf4j-simple และ log4j ในเวลาเดียวกันกับการสาธิต:
นี่เป็นเพราะมีสาม "org/slf4j/impl/staticloggerbinder.class" ที่มีอยู่ ในเวลานี้คำสั่งเอาท์พุทคอนโซลเมธอดของรายงานผลงาน MultipleBindingUtuity::
Private Static Void ReportMultipleBindingAbtuity (SET <URL> bindPathSet) {ถ้า (isAbsAbliousTaticLoggerBinderPathSet (BinderPathSet)) {util.Report ("เส้นทางคลาสมีการผูก SLF4J หลายครั้ง"); สำหรับ (เส้นทาง URL: bindpathSet) {util.Report ("พบการเชื่อมโยงใน [" + path + "]"); } util.Report ("ดู" + multiple_bindings_url + "สำหรับคำอธิบาย"); -จากนั้นชาวเน็ตอาจถามว่าฉันควรทำอย่างไรถ้ามีสาม "org/slf4j/impl/staticloggerbinder.class" ในเวลาเดียวกัน? ก่อนอื่นจะมีการพิจารณาว่าสิ่งนี้จะไม่ทำให้เกิดข้อผิดพลาดในการเริ่มต้นและประการที่สองในระหว่างการรวบรวมคอมไพเลอร์จะเลือกหนึ่งใน staticloggerbinder.class สำหรับการผูก
ในที่สุด StaticLoggerBinder นั้นค่อนข้างง่าย StaticLoggerBinders ที่แตกต่างกันมีการใช้งานที่แตกต่างกันของ GetLoggerFactory หลังจากได้รับ IloggerFactory ให้โทรหา GetLogger และรับเครื่องบันทึกเฉพาะ คุณสามารถใช้ Logger สำหรับเอาต์พุตบันทึก
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น