SLF4J هي طبقة تجريد إطار عمل ، والتي تربط أطراف السجل المحددة ، مثل 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 أو Commons-Logging هي طبقة التكيف هذه ، و SLF4J هي كائن هذا البحث الورقي.
من الوصف أعلاه ، يجب أن نعرف بوضوح شيئًا واحدًا: SLF4J هو مجرد معيار تسجيل ، وليس تطبيقًا محددًا لنظام التسجيل. من المهم جدًا فهم هذه الجملة. يذكر SLF4J فقط القيام بأمرين:
SLF4J البافسي والأسود كلاهما تطبيقات محددة من SLF4J. لا يقوم Log4J بتنفيذ SLF4J مباشرة ، ولكن هناك جسر خاص للطبقة الأولى SLF4J-LOG4J12 لتنفيذ SLF4J.
من أجل فهم SLF4J بشكل أفضل ، ننظر أولاً إلى الأمثلة ثم نقرأ الكود المصدري. أعتقد أن القراء سيكون لديهم فهم أعمق لـ SLF4J.
مثال تطبيق SLF4J
كما ذكر أعلاه ، فإن التنفيذ المباشر/غير المباشر لـ SLF4J يتضمن SLF4J Simple ، Logback ، SLF4J-LOG4J12. دعونا أولاً نحدد pom.xml ونقدم حزمة الجرة ذات الصلة:
<!-النص الأصلي: candgjie في مايو http://www.cnblogs.com/xrq730/p/8619156.html-> <project xmlns = "http://maven.apache.org/pom/4.0.0" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" <DodelVersion> 4.0.0 </domedversion> <rougiD> org.xrq.log </rougiD> <StifactId> اختبار log </shintifactid> <sored> 1.0.0 </version> <caping> jar </packaging> <same> log-test </name> <project.build.sourceencoding> utf-8 </project.build.sourceencoding> </seperties> <Eperenceies> <eredency> <roupiD> Junit </rougiD> </artifactid> Junit </stifactid> <roughId> org.slf4j </rougiD> <StifactId> slf4j-api </stiftiD> <الإصدار> 1.7.25 </version> </sependency> <reperence> <roupid> ch.qos.logback </groupid> <Gropled> org.slf4j </rougiD> <StifactId> slf4j-simple </stifactid> <الإصدار> 1.7.25 </version> </dependency> <sependency> </groupid> log4j </rougeid> <StifactId> log4j </spensid> <roughid> org.slf4j </rougiD> <StifactId> slf4j-log4j12 </shintifactid> <soph> 1.7.21 </version> </sependency> </enependencies> </project>
اكتب رمز Java بسيط:
testpublic void testSlf4j () {logger logger = loggerfactory.getLogger (object.class) ؛ logger.error ("123") ؛ }بعد ذلك ، نعلق أولاً الخطوط 30 إلى 49 من pom.xml أعلاه ، أي أننا لا نقدم أي فئة تنفيذ SLF4J وتشغيل طريقة الاختبار. لنلقي نظرة على إخراج وحدة التحكم على النحو التالي:
عند رؤية الإخراج دون أي سجلات ، يتحقق هذا من وجهة نظرنا: لا يوفر SLF4J تطبيقًا محددًا للسجلات ، ولا يمكن SLF4J فقط طباعة السجلات.
ثم افتح التعليق التوضيحي الكلاسيكي للأسود وقم بتشغيل طريقة الاختبار. لنلقي نظرة على إخراج وحدة التحكم على النحو التالي:
لقد رأيت أننا نحتاج فقط إلى تقديم فئة تنفيذ محددة من SLF4J ، ويمكننا استخدام إطار السجل لإخراج السجل.
أخيرًا ، نقوم بإجراء اختبار. نحن نفتح جميع السجلات ، ونقدم كلاسيكيات التسجيل ، و SLF4J simple ، و log4j ، وتشغيل طريقة الاختبار ، وإخراج وحدة التحكم هو:
الفرق من ما سبق هو أنه يمكنك إخراج سجلات ، ولكن سيتم إخراج بعض سجلات الإنذار ، مما دفعنا إلى تقديم تطبيقات SLF4J متعددة في نفس الوقت ، ثم حدد أحدها كنظام السجل الذي نستخدمه.
من المثال ، يمكننا استخلاص استنتاج مهم ، أي دور SLF4J: طالما أن جميع التعليمات البرمجية تستخدم كائن الواجهة SLF4J ، لا نحتاج إلى الاهتمام بتنفيذها المحدد. في النهاية ، يمكن استخدام تطبيق واحد محدد في جميع الأماكن ، والاستبدال والصيانة مريحة للغاية.
مبدأ تنفيذ SLF4J
لقد نظرت إلى مثال SLF4J أعلاه ، وسأدرس تنفيذ SLF4J أدناه. سوف نركز فقط على الكود الرئيسي.
استخدام SLF4J هو جملة لا تزال دون تغيير على مدار السنة ، "logger logger = loggerfactory.getLogger (object.class) ؛" ، مما يدل على أن هذا هو استخدام LoggerFactory للحصول على تطبيق محدد لواجهة مسجل توفره SLF4J. يتم تنفيذ طريقة getLogger لـ LoggerFactory على النحو التالي:
logger static public getLogger (class <؟> clazz) {logger logger = getLogger (clazz.getName ()) ؛ if (detect_logger_name_mismatch) {class <؟> classeptutCallingClass = util.getCallingClass () ؛ if (autoCompatedCallingClass! = null && nonmatchingclasses (clazz ، clazz ، autoCompatedCallingClass)) {util.Report (string.format ("name logger name miskatch. المعطى: /" ٪ s /" util.report ("انظر" + logger_name_mismatch_url + "للحصول على شرح") ؛ }} logger ؛}ابدأ بالرمز من السطر 2 واتبع طريقة bind () إلى loggerFactory:
BIND VOID الثابتة النهائية الخاصة () {try {set <Url> staticloggerBinderPathset = null ؛ // تخطي التحقق تحت Android ، انظر أيضًا // http://jira.qos.ch/browse/slf4j-328 if (! isandroid ()) {StaticLoggerBinderPathset = findpossiblestaticloggerbinderpathset () ؛ reportMultipleBindingambiGuity (StaticLoggerBinderPathset) ؛ } // السطر التالي يقوم بربط staticloggerbinder.getsingleton () ؛ initialization_state = success_initialization ؛ ReportActualBinding (StaticLoggerBinderPathset) ؛ FixSubStituteLoggers () ؛ Redayevents () ؛ // إطلاق جميع الموارد في subst_factory subst_factory.clear () ؛ } catch (noclassDeffounderror ncde) {string msg = ncde.getMessage () ؛ if (messageContainsorgSlf4jimplstaticLoggerBinder (msg)) {initialization_state = nop_fallback_initialization ؛ util.report ("فشل في تحميل الفئة /"org.slf4j.impl.StaticLoggerBinder/". ") ؛ util.Report ("التخلف عن تنفيذ مسجل عدم التعاون (NOP)") ؛ util.report ("انظر" + no_staticloggerbinder_url + "لمزيد من التفاصيل.") ؛ } آخر {fansbinding (ncde) ؛ رمي NCDE. }} catch (java.lang.nosuchmethoderror nsme) {string msg = nsme.getMessage () ؛ if (msg! = null && msg.contains ("org.slf4j.impl.StaticLoggerBinder.getsingleton ()")) {initialization_state = fant_initialization ؛ Util.Report ("SLF4J-API 1.6.x (أو لاحقًا) غير متوافق مع هذا الربط.") ؛ util.report ("الربط الخاص بك هو الإصدار 1.5.5 أو قبل.") ؛ util.report ("ترقية الربط الخاص بك إلى الإصدار 1.6.x.") ؛ } رمي nsme ؛ } catch (استثناء e) {fansbinding (e) ؛ رمي جديد غير قانوني ("فشل تهيئة غير متوقع" ، هـ) ؛ }}السطر 7 من هذا المكان مفتاح ، انظر إلى الكود:
مجموعة ثابتة <Url> findpossiblestaticloggerbinderpathset () {// استخدم SET بدلاً من القائمة من أجل التعامل مع الأخطاء #138 // LinkedHashSet مناسبة هنا لأنها تحافظ حاول {classloader loggerfactoryclasslaxloader = loggerfactory.class.getClassLoader () ؛ التعداد <Url> مسارات ؛ if (loggerfactoryclasslassloader == null) {paths = classloader.getSystemResources (static_logger_binder_path) ؛ } آخر {paths = loggerfactoryclassloader.getResources (static_logger_binder_path) ؛ } بينما (المسارات staticloggerbinderpathset.add (path) ؛ }} catch (ioException ioe) {util.report ("خطأ الحصول على الموارد من المسار" ، ioe) ؛ } إرجاع staticloggerbinderpathset ؛}النقطة الرئيسية في هذا المكان هي في الواقع الرمز في السطر 12. عند الحصول على logger ، ستذهب إلى classpath للعثور على static_logger_binder_path. قيمة static_logger_binder_path هي "org/slf4j/inment/staticloggerbinder.class" ، أي جميع تطبيقات SLF4J ، تحت مسار حزمة الجرة المقدمة ، يجب أن يكون هناك "org/slf4j/inmsloggerbinder.class". يمكننا إلقاء نظرة:
لا يمكننا تجنب إدخال تطبيقات SLF4J متعددة في النظام في نفس الوقت ، وبالتالي فإن مكان الاستلام هو مجموعة. يجب أن تلاحظ أنه سيكون هناك تحذيرات عندما يقدم الجزء أعلاه التسجيل ، SLF4J البسيط ، و log4j في نفس الوقت مثل العرض التوضيحي:
هذا لأن هناك ثلاثة "org/slf4j/inment/staticloggerbinder.class" موجودة. في هذا الوقت ، بيان إخراج Console Console ReportMultipleBindingambiGive:
private static void reportmultiplebindingambiGuity (set <Url> bindPathset) {if (isambiubuuleStaticLoggerBinderPathset (BinderPathset)) {util.report ("مسار الفئة يحتوي على ارتباطات متعددة SLF4J.") ؛ لـ (مسار url: bindPathset) {util.report ("تم العثور على ربط في [" + path + "]") ؛ } util.report ("انظر" + mustion_bindings_url + "للحصول على شرح.") ؛ }}ثم قد يسأل مستخدمو الإنترنت ، ما الذي يجب علي فعله إذا كان هناك ثلاثة "org/slf4j/inms/staticloggerbinder.class" في نفس الوقت؟ بادئ ذي بدء ، يتم تحديد أن هذا لن يتسبب في حدوث خطأ في بدء التشغيل ، وثانياً ، أثناء التجميع ، سيقوم برنامج التحويل البرمجي باختيار أحد staticloggerbinder.class للربط.
أخيرًا ، StaticLoggerbinder بسيط نسبيًا. لدى staticloggerbinders المختلفة تطبيقات مختلفة من getLoggerFactory. بعد الحصول على IloggerFactory ، اتصل بـ getLogger واحصل على المسجل المحدد. يمكنك استخدام المسجل لإخراج السجل.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.