लकड़हारा निजी स्थिर होना चाहिए या नहीं


103

लकड़हारे को स्थिर घोषित किया जाना चाहिए या नहीं? आमतौर पर मैंने लकड़हारे के लिए दो प्रकार की घोषणा देखी है:

    संरक्षित लॉग लॉग = नया Log4JLogger (aClass.class);

या

    निजी स्थिर लॉग लॉग = नया Log4JLogger (aClass.class);

किसका उपयोग करना चाहिए? क्या समर्थक और चोर दोनों के हैं?


1
लॉगिंग एक क्रॉस-कटिंग चिंता है। पहलू का प्रयोग करें और सवाल है।
डेव जार्विस

4
staticप्रति वर्ग एक संदर्भ है। गैर-स्थिर एक उदाहरण प्रति संदर्भ (+ आरंभीकरण) है। तो कुछ मामलों में, बाद में महत्वपूर्ण स्मृति प्रभाव पड़ता है यदि आपके पास कई उदाहरण हैं। कभी नहीं एक में गैर स्थिर का उपयोग लगातार वस्तु। मैं हमेशा स्थिर संस्करण का उपयोग करता हूं। (जो कि अपरकेस होना चाहिए LOG)
है क्विट - Anony-Mousse

2
जैसा कि पहले ही सुझाव दिया गया है, उदाहरण के लिए AOP और एनोटेशन का उपयोग करें: jcabi.com/jcabi-aspects/annotation-loggable.html
yegor256

1
स्थिर संस्करण का रॉबर्टह्यूम एक निरंतर उपयोग कर रहा है। यही कारण है कि यह बड़े पैमाने पर होना चाहिए।
QUIT - Anony-Mousse

2
नहीं यह होना चाहिए private static final Log logकि लोअरकेस है। लकड़हारा स्थिर नहीं है, लकड़हारा एक स्थिर अंतिम वस्तु है (जिसे उत्परिवर्तित किया जा सकता है)। व्यक्तिगत रूप से मैं हमेशा उपयोग करता हूं logger
ऑसुंडब्लैड

जवाबों:


99

गैर-स्थैतिक रूप का लाभ यह है कि आप इसे (सार) बेस क्लास में घोषित कर सकते हैं जैसे कि इस चिंता के बिना कि सही क्लासनाम का उपयोग किया जाएगा:

protected Log log = new Log4JLogger(getClass());

हालांकि इसका नुकसान जाहिर है कि वर्ग के हर उदाहरण के लिए एक नया लकड़हारा उदाहरण बनाया जाएगा। यह प्रति से महंगा नहीं हो सकता है, लेकिन यह एक महत्वपूर्ण उपरि जोड़ता है। यदि आप इससे बचना चाहते हैं, तो आप staticइसके बजाय फ़ॉर्म का उपयोग करना चाहेंगे । लेकिन इसका नुकसान यह है कि आपको इसे प्रत्येक व्यक्तिगत वर्ग में घोषित करना होगा और हर वर्ग को ध्यान रखना होगा कि लकड़हारे के निर्माण के दौरान सही क्लासनाम का उपयोग किया जाता है क्योंकि getClass()इसका उपयोग स्थिर संदर्भ में नहीं किया जा सकता है। हालांकि, औसत आईडीई में आप इसके लिए एक स्वत: पूर्ण टेम्पलेट बना सकते हैं। जैसे logger+ctrl+space

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

protected Log log = LogManager.getLogger(getClass());

6
abstract Log getLogger();अमूर्त वर्ग में घोषणा । इस विधि को लागू करें, विशेष उदाहरण के लिए स्थैतिक लकड़हारा लौटा। private final static Log LOG = LogManager.getLogger(Clazz.class);अपने IDE वर्ग टेम्पलेट में जोड़ें ।
QUIT -

2
Slf4j के लिए:protected Logger log = LoggerFactory.getLogger(getClass());
मार्कस Pscheidt

3
@BalusC getLogger विधि से getClass () पास करने में समस्या यह है कि यह वर्तमान उदाहरण के वर्ग को लौटाता है। आम तौर पर यह अधिक वांछित है कि लॉगिंग उस वर्ग के साथ जुड़ा हो जहां कोड है। उदाहरण के लिए यदि लॉगिंग कोड अभिभावक वर्ग में है तो हम चाहते हैं कि लॉगिंग अभिभावक के साथ भी जुड़ा हो, भले ही क्रियान्वयन का उदाहरण है और कक्षा के बच्चे का उदाहरण जो अभिभावक का उप-वर्ग है। GetClass () यह, गलत तरीके से बच्चे के साथ संबद्ध किया जाएगा के साथ
INOR

@inor: "गलत तरीके से"? यदि आप क्लास को एब्स्ट्रैक्ट नहीं करना चाहते हैं, तो आपको पहले से विरासत में मिले गेटक्लास () का उपयोग नहीं करना चाहिए। ऐसे डेवलपर हैं जो इसे सही और उपयोगी पाते हैं क्योंकि यह उन सूचनाओं को प्रकट करता है जिनमें उप-तर्क बिल्कुल तर्क का प्रदर्शन किया गया है।
बालुस

2
@ BalusC getLogger (getClass ()) परिणाम हमेशा उप-वर्ग के नाम को गलत तरीके से लॉग करता है। क्लास क्लाज में कोड द्वारा बनाई गई लॉगिंग को जोड़ने के लिए लॉगिंग क्लासेस को हमेशा GetLogger (Clazz.class) करना चाहिए। डेवलपर्स जो यह जानना चाहते हैं कि उप-वर्गों में से कौन सा क्रियान्वित हो रहा है (उदाहरण के लिए SubClazz का विस्तार Clazz) को SubClazz में करना चाहिए: getLogger (SubClazz.class) और कुछ ऐसा: log.info ("मेरे बेस क्लास में कुछ <> कॉल करना");
inor

44

मैं समझता था कि सभी लॉगर स्थिर होने चाहिए; हालाँकि, wiki.apache.org पर यह लेख कक्षावार लीक के संबंध में कुछ महत्वपूर्ण स्मृति चिंताओं को सामने लाता है। एक लकड़हारे को स्थिर घोषित करने से घोषित वर्ग (और संबद्ध क्लास लोडर) को J2EE कंटेनरों में कचरा एकत्र होने से रोकता है जो एक साझा क्लास लोडर का उपयोग करते हैं। यदि आप अपने एप्लिकेशन को पर्याप्त समय पर पुनः लोड करते हैं, तो यह आपको PermGen त्रुटियों का परिणाम देगा।

मैं वास्तव में इस क्लास लोडर लीक मुद्दे के आसपास काम करने का कोई तरीका नहीं देखता, अन्य लोगों को गैर-स्थैतिक घोषित करने के अलावा।


4
मुझे संदेह था कि स्टैटिक फील्ड में मेमोरी लीक की समस्या होगी। गैर-स्थैतिक में प्रदर्शन की समस्या हो सकती है जैसा कि अन्य ने कहा है। फिर आदर्श तरीका क्या है?
लियांग

@piepera आपके द्वारा संदर्भित लेख में वर्णित मुख्य समस्या प्रत्येक एप्लिकेशन में लॉगिंग स्तर को नियंत्रित करने की क्षमता है जब "उस स्थिति पर विचार करें जब" निजी स्टेटिक लॉग लॉग = "का उपयोग कर एक क्लास को क्लासडैडर के माध्यम से तैनात किया जाता है जो कई माना जाता है के वंश में है स्वतंत्र "अनुप्रयोग"। मैं यह नहीं देखता कि एक समस्या के रूप में क्योंकि इस विशेष स्थिति में अनुप्रयोगों में एक "कॉमन ग्राउंड" होता है और उस "कॉमन ग्राउंड" में क्लास के लिए लॉगिंग स्तर तय किया जाता है और हाँ, यह सभी एप्लीकेटन के लिए है ... लेकिन रखें ध्यान में रखते हुए कि यह वर्ग इन अनुप्रयोगों के बाहर [भरा हुआ] है
inor

17

सबसे महत्वपूर्ण अंतर यह है कि यह आपकी लॉग फ़ाइलों को कैसे प्रभावित करता है: लॉग किस श्रेणी में जाते हैं?

  • आपकी पहली पसंद में, एक उपवर्ग के लॉग सुपरक्लास की श्रेणी में समाप्त हो जाते हैं। यह मुझे बहुत ही सहज लगता है।
  • आपके पहले मामले का एक प्रकार है:

    संरक्षित लॉग लॉग = नया Log4JLogger (getClass ());

    उस स्थिति में, आपकी लॉग श्रेणी कहती है कि जो कोड लॉग किया गया था, उस पर कौन सी वस्तु काम कर रही है।

  • आपकी दूसरी पसंद (निजी स्थिर) में, लॉग श्रेणी वह वर्ग है जिसमें लॉगिंग कोड होता है। तो आम तौर पर वह वर्ग जो उस चीज को कर रहा है जिसे लॉग किया जा रहा है।

मैं उस अंतिम विकल्प की जोरदार सिफारिश करूंगा। अन्य समाधानों की तुलना में इसके ये फायदे हैं:

  • लॉग और कोड के बीच एक सीधा संबंध है। यह पता लगाना आसान है कि लॉग संदेश कहां से आया है।
  • यदि किसी को लॉगिंग स्तरों (जो प्रति श्रेणी के अनुसार किया जाता है) को ट्यून करना होता है, तो यह आमतौर पर होता है क्योंकि वे किसी विशेष संदेश में लिखे गए कुछ विशेष संदेशों में रुचि रखते हैं (या नहीं)। यदि श्रेणी वह वर्ग नहीं है जो संदेशों को लिख रहा है, तो स्तरों को ट्यून करना कठिन है।
  • आप स्थैतिक तरीकों से लॉग इन कर सकते हैं
  • लॉग ऑन करने के बजाय लॉग ऑन करने के लिए लॉगर्स को केवल एक बार प्रतिरूपित (या देखा गया) करने की आवश्यकता है।

इसके नुकसान भी हैं:

  • इसे हर उस वर्ग में घोषित किया जाना चाहिए जहाँ आप संदेश लॉग करते हैं (सुपरक्लास लॉगर्स का पुन: उपयोग नहीं)।
  • लकड़हारा शुरू करते समय सही classname लगाने के लिए आपको ध्यान रखने की आवश्यकता है। (लेकिन आपके लिए अच्छे IDE का ध्यान रखें)।

4

नियंत्रण के व्युत्क्रम का उपयोग करें और निर्माता में लकड़हारा पास करें। यदि आप उस वर्ग के अंदर लकड़हारा पैदा करते हैं जो आपके यूनिट परीक्षणों के साथ एक समय का शैतान है। आप लिख रहे हैं इकाई परीक्षण आप नहीं हैं?


5
यूनिट परीक्षण जो लॉगिंग की जांच करते हैं आप ध्वनि को बेकार और अविश्वसनीय रूप से भंगुर दोनों पैदा कर रहे हैं।
माइकल

1
परीक्षण के तहत प्रणाली के आधार पर उपयोगिता। कभी-कभी लॉगिंग आप सभी के लिए है।
वेन एलन

@Wayne एलन जब आप इकाई परीक्षण कर रहे हैं, तो परिभाषा के अनुसार, आपके पास परीक्षण के परिणाम भी हैं। क्या आप ऐसी स्थिति का सुझाव दे रहे हैं जिसमें कोई इकाई परीक्षण करता है लेकिन परीक्षण परिणाम नहीं है? केवल लॉग हैं?
इनर

वर्ग के अंदर लकड़हारा पैदा करने से समस्याएं पैदा नहीं होती हैं। क्या आप एक साधारण उदाहरण दिखा सकते हैं जो UT के लिए कठिन है क्योंकि वर्ग अपना लकड़हारा बनाता है?
इनर

1
ज़रूर। कैसे एक लकड़हारा जो ईमेल भेजता है। हर बार जब आप अपने परीक्षण चलाते हैं, तो ऐसा मत करना। प्लस आप साइड इफेक्ट को कैसे मुखर करते हैं?
वेन एलन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.