क्या Logger.getLogger (MyClass.class) log4j लॉगर्स को इनिशियलाइज़ करने का सबसे अच्छा तरीका है?


13

इस Mkyong ट्यूटोरियल इस तरह से लकड़हारे को सुझाव देता है:

@Controller
public class WelcomeController {

    private static final Logger logger = Logger.getLogger(WelcomeController.class);

   // etc

}

अब निश्चित रूप से आपके द्वारा उपयोग किया जाने वाला हर दूसरा वर्ग, उसी तरह एक लकड़हारा अपने लकड़हारा को इनिशियलाइज़ करेगा।

मेरा सवाल है - क्या यह करने का सबसे अच्छा तरीका है? ऐसा लगता है ... दोहराव।


2
आप इस बारे में क्या कहते हैं (जावा के सिंटैक्स को अलग करना)? आपको लकड़हारा रखने के लिए एक चर बनाना होगा, और आपको getLogger()पाने के लिए लकड़हारे का नाम बताना होगा।
kdgregory

2
@kdgregory ने कहा कि मैं हर वर्ग में एक ही काम कर रहा हूं।
dwjohnston


3
माइग्रेट करने के लिए बहुत पुराना है, लेकिन यह सवाल यहां ऑफ-टॉपिक है और स्टैकऑवरफ्लो के लिए अधिक उपयुक्त है।
एंड्रेस एफ।

1
@AndresF। मुझे लगता है कि मैंने इसे यहां रखा है क्योंकि यह तकनीकी समस्या की तुलना में कोड शैली / डिजाइन पैटर्न के बारे में अधिक सवाल है।
dwjohnston

जवाबों:


16

आपकी टिप्पणी कहती है कि "वर्बोज़" से तात्पर्य हर वर्ग में कोड की इस पंक्ति को दोहराने की आवश्यकता से है। मेरी पहली प्रतिक्रिया यह है कि बड़ी तस्वीर में, हर वर्ग के लिए कोड की दो पंक्तियों (चर परिभाषा प्लस आयात विवरण) को जोड़ना बड़ी बात नहीं है। खासकर जब से आपको केवल उन वर्गों से जोड़ना होगा जिनके पास व्यवहार है और इसलिए लॉगिंग करने की आवश्यकता है। उस ने कहा, कोड की विशिष्ट पंक्ति जो आप उपयोग कर रहे हैं, कॉपी-पेस्ट त्रुटियों (उस पर बाद में) के लिए प्रवण है।

लेकिन, जब से आप विकल्प चाहते हैं, यहां कुछ कारण हैं, जिनके कारण आप उनका उपयोग करना चाहते हैं या नहीं कर सकते हैं।

पूरे ऐप के लिए सिंगल लकड़हारे का उपयोग करें

यदि आप इस बात की परवाह नहीं करते हैं कि कौन सी कक्षा रिपोर्टिंग कर रही है, या संदेश में सभी आवश्यक संदर्भ डालने के लिए तैयार हैं, तो एक साधारण सिंगलटन लकड़हारा नौकरी करेगा:

LoggerSingleton.getInstance().debug("MyController is running")

मेरी राय में, लॉगिंग ढांचे के बड़े लाभों में से एक अलग लकड़हारा उदाहरणों द्वारा प्रदान किया गया संदर्भ है - यदि केवल लॉग संदेशों को विभिन्न गंतव्यों तक निर्देशित करना है। मैं कोड की एक पंक्ति (आप अभी भी आयात की जरूरत है) को बचाने के लिए उसे नहीं दूंगा।

इसके अलावा, यह उपयोग के बिंदु पर वर्बोसिटी बढ़ाता है, जो कि अधिक कीस्ट्रोक्स में समाप्त होगा।

उपयोग के बिंदु पर अपने लकड़हारे बनाएँ

मैं इसे केवल इसलिए बाहर फेंक रहा हूं क्योंकि यह चर को समाप्त करता है। मुझे नहीं लगता कि मुझे इस पर टिप्पणी करने की आवश्यकता है। यद्यपि यह एक लकड़हारा उदाहरण प्राप्त करने के लिए मेरी पसंदीदा तकनीक दिखाता है।

Logger.getLogger(getClass()).debug("blah blah blah");

लकड़हारे को इंजेक्ट करने के लिए बीन पोस्ट-प्रोसेसर का उपयोग करें

आपका उदाहरण स्प्रिंग का उपयोग करता है, और स्प्रिंग आपको बीन इनिशियलाइज़ेशन कोड में हुक करने देता है। आप एक पोस्ट-प्रोसेसर बना सकते हैं जो loggerसदस्य चर के लिए बीन का निरीक्षण करता है , और Loggerजब वह एक पाता है तो एक उदाहरण बनाता है ।

हालांकि इस तरह के पोस्ट-प्रोसेसर कोड की केवल कुछ दर्जन लाइनें हैं, यह आपके आवेदन में एक और गतिशील हिस्सा है, और इसलिए बग का एक और संभावित स्रोत है। मैं उनमें से कम से कम संभव है पसंद करते हैं।

एक मिश्रण का उपयोग करें

स्काला और ग्रूवी लक्षण प्रदान करते हैं , जो आपको व्यवहार को संक्षिप्त करते हैं। एक विशिष्ट स्काला पैटर्न एक Loggingविशेषता बनाने के लिए है , फिर इसे उस वर्ग में जोड़ें, जिसे लॉगिंग की आवश्यकता है:

class MyController with Logging

दुर्भाग्य से, इसका मतलब है कि आपको भाषाओं को बदलना होगा। जब तक आप जावा 8 का उपयोग नहीं कर रहे हैं, उस स्थिति में आप Logging"डिफ़ॉल्ट विधि" के साथ एक इंटरफ़ेस बना सकते हैं :

public interface Logging {
    default Logger getLogger() {
        return Logger.getLogger(getClass());
    } 
}

अब, अपने वर्ग कोड के भीतर, आप बस उपयोग कर सकते हैं

getLogger().debug("blah blah blah");

जबकि आसान, इसके कुछ नुकसान हैं। एक बात के लिए, यह इसका उपयोग करने वाले हर वर्ग के इंटरफ़ेस को प्रदूषित करता है, क्योंकि सभी इंटरफ़ेस विधियाँ सार्वजनिक हैं। शायद यह बुरा नहीं है यदि आप इसे केवल उन वर्गों के लिए उपयोग करते हैं जो तत्काल और इंजेक्शन द्वारा स्प्रिंग हैं, खासकर यदि आप इंटरफ़ेस / कार्यान्वयन पृथक्करण का पालन करते हैं।

इससे भी बड़ी समस्या यह है कि इसे हर कॉल पर वास्तविक लकड़हारा उदाहरण देखना पड़ता है। जो तेज है, लेकिन अनावश्यक है।

और आपको अभी भी आयात विवरण की आवश्यकता है।

लकड़हारे को सुपरक्लास में ले जाएं

मैं दोहराऊंगा: मुझे बार-बार लकड़हारा परिभाषाएं नहीं मिलती हैं, लेकिन अगर आपको लगता है कि मैं उन्हें खत्म करने का सबसे अच्छा तरीका है।

public abstract class AbstractController {
    protected Logger logger = Logger.getLogger(getClass());
}

अब आपकी कंट्रोलर क्लासेस इनहेरिट करती हैं AbstractController, और उनकी पहुंच loggerवैरिएबल तक होती है। याद रखें कि आपको @Controllerएनोटेशन को ठोस वर्ग पर रखना होगा ।

कुछ लोग इसे वंशानुक्रम का विकृति पाएंगे। मैंने कक्षा के AbstractControllerबजाय नामकरण करके उन्हें शांत करने की कोशिश की है AbstractProjectClass। आप अपने लिए तय कर सकते हैं कि वहाँ एक रिश्ता है या नहीं ।

अन्य लोग एक स्थिर चर के बजाय एक उदाहरण चर के उपयोग पर आपत्ति करेंगे। IMO स्टैटिक लॉगर कॉपी-पेस्ट त्रुटियों से ग्रस्त हैं, क्योंकि आपको स्पष्ट रूप से क्लासनाम का संदर्भ देना है; getClass()यह सुनिश्चित करता है कि आपका लकड़हारा हमेशा सही रहे।


मुझे लगता है कि आपको वंशानुक्रम वर्ग में GetClass () के बारे में सावधान रहना चाहिए, MethodHandles.lookup ()। लुकअपक्लास () jdk 7 के बाद बेहतर है
yuxh

@ लक्स - क्या आपके पास इसके लिए स्पष्टीकरण है?
kdgregory

यहां देखें: stackoverflow.com/a/6653577/4652536
yuxh

@yuxh - उस प्रश्न में MethodHandles का एकमात्र उल्लेख (जो आपके द्वारा लिंक किए गए उत्तर में नहीं था), स्पष्टीकरण के लिए पूछने वाली टिप्पणी के साथ एक समान असमर्थित कथन है। क्या आपके पास उस दावे के लिए आधिकारिक समर्थन है जो इससे MethodHandles.lookup().lookupClass()बेहतर है Object.getClass()?
kdgregory

MethodHandles.lookup().lookupClass()स्थिर चर के लिए इस्तेमाल किया जा सकता है, कॉपी-पेस्ट त्रुटियों के लिए प्रवण नहीं है और तेजी से है: stackoverflow.com/a/47112323/898747 इसका मतलब है कि यह एक अतिरिक्त इनपोर्ट है, लेकिन मुझे मेरे लकड़हारा स्थिर की तरह काफी पसंद है, इसलिए यह कम से कम लायक है उल्लेख :)
FableBlaze

0

@Kdgregory द्वारा उपलब्ध कराए गए उत्तर का विस्तार करने के लिए, ग्रूवी एक एनोटेशन के रूप में बॉक्स से बाहर @Slf4j( groovy.util.logging.Slf4j) प्रदान करता है जो इसे एक लकड़हारे से निपटने के लिए वर्ग पर एएसटी परिवर्तन करता है जो logडिफ़ॉल्ट रूप से चर नाम को मानता है यदि अनिर्दिष्ट हो।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.