現在很多開源項目在使用LOG的時候做了不好的示范--在基類中實例化的方式使用LOG,而不是靜態變量。

          例如:

          class Base  {
               private final Log LOG = LogFactory.getLog(this.getClass());
          }

          class Derived  {
              public void foo() {
                     if (LOG.isDebugEnabled()) LOG.debug("foo");
              }
          }

          這種用法,當類被繼承的時候,LOG就完全亂了。spring、struts都有這樣的問題。

          正確的使用方式應該是直接靜態化聲明LOG。

          例如:

          class DerivedA  {
               private final static Log LOG = LogFactory.getLog(DerivedA.class);
          }



          --------------------------
          盛大招聘.Net開發工程師
          經典好書:.NET框架程序設計(修訂版)
          新聞:2008年最精彩科技圖片:電流運動模擬圖居首
          導航:博客園首頁  知識庫  新聞  招聘  社區  小組  博問  網摘  找找看
          文章來源:http://www.cnblogs.com/jobs/archive/2009/01/05/1368894.html
          posted on 2009-01-05 10:49 溫少的日志 閱讀(2476) 評論(13)  編輯  收藏
          Comments
          • # re: 也說一種普遍錯誤使用的LOG方式
            seewood
            Posted @ 2009-01-05 11:38
            不同以上的說法,我認為并不存在孰優孰劣。一、我認為應該看被聲明Log實例的對象在應用中的作用,很多項目將其作為非靜態變量聲明,是因為log所在的類是一個Service,在ServerSide只會被實例化一次,那么使用非靜態的實例,就并不比靜態來的更耗。二在需要繼承的時候,使用非靜態就更簡單,子類的this.getClass()得到子類的類型,就自動與父類的log區別開了。基于這兩個理由,我覺得在使用協作類的時候,使用實例方式聲明更優;而在實例類中使用時,使用靜態方式聲明更優。  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            溫少的日志
            Posted @ 2009-01-05 11:47
            @seewood
            不是因為性能的問題,是因為繼承時會導致LOG錯亂,例如你繼承了Spring的ClassPathXmlApplicationContext時,日志輸出的的類名不對了。  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            隔葉黃鶯
            Posted @ 2009-01-05 11:53
            從哪里輸出日志,當然類名就是它了,而不應該是基類,所以用 private final Log LOG = LogFactory.getLog(this.getClass());

            如果是寫成 private final static Log LOG = LogFactory.getLog(DerivedA.class);

            的話,那么類層次中的每一個類,都要聲明一個靜態的 LOG,好像也很少有人會用全大寫的 LOG 命名。  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            溫少的日志
            Posted @ 2009-01-05 12:23
            @隔葉黃鶯
            你的說法不對,例如LOG4J能夠把記錄日志的類和代碼行數輸出,如果使用
            protected final Log LOG = LogFactory.getLog(this.getClass())的方式,就會導致不能夠簡單的方式定位問題了。

            使用全大寫的方式挺好的,最初在JXTA中看到這種用法,反復比較之后,覺得使用大寫LOG比小寫logger更清晰。  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            3220
            Posted @ 2009-01-05 12:35
            1)我覺得還是需要分析性能的,例如在 spring+hibernate+struts2的框架下,對應一個jsp請求,需要創建的實例非常多,因此一個沒有開發的很好的Log的實例的創建很有可能因為多次創建而影響性能。

            2) 使用 final Log log的形式確實會造成日志的記錄層次混亂,尤其是Service層。

            因此,我們需要在不同的場景下使用不同的方式,不能千篇一律,例如spring,struts等不能說是使用不當,我覺得在基礎框架層的代碼中需要更多的考慮性能,而且我們基本不會對框架的日志進行過細的分類過濾處理。
            (我覺得日志的分類主要是應用在過濾分類中,具體你需要了解哪一個類出現問題了,一般日志紀錄的格式中都可以標明文件名、行號,因此不需要做過細的過濾分類定義的時候完全可以使用基類的名字)  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            溫少的日志
            Posted @ 2009-01-05 14:35
            @3220
            性能這兩種方式是非常接近的,而且static聲明的方式性能會更好,實例化的方式更方便,struts、spring都采用了更方便的做法,但是更方便的做法,就會在類被繼承的時候導致LOG輸出混亂。像struts、spring框架的類通常不會被繼承,但總是存在一些情況需要繼承的,一旦出現繼承框架的類,例如你編寫一個類繼承自ClassPathXmlApplicationContext,那么LOG輸出就會產生混亂的。

            綜合比較:
            方式A 基類實例化Log LOG = LogFactory.getLog(this.getClass())
            方式B 每個類單獨聲明 static Log LOG = LogFactory.getLog(XXX.class)
            性能 兩種方式接近
            方便 方式A更方便,不需要再子類中再聲明。
            不良后果 在類被繼承時,使用方式A會導致日志輸出混亂  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            隔葉黃鶯
            Posted @ 2009-01-05 14:38
            @溫少的日志
            不太清楚在什么時候,用LogFactory.getLog(this.getClass())不能正確輸出行號和方法

            @3220
            如果是spring+hibernate+struts1 的應用,因為 Service/Dao/Action 類都基本是表現為單例,所以性能上與用靜態的 log 無甚差異。

            只有在使用 spring+hibernate+struts2,才會是獨立請求用不同的 Action 實例,這樣的實例變量對性能影響我想應該也不大。

            基礎框架的日志我們在實際的使用中都是只在錯誤時輸出。  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            溫少的日志
            Posted @ 2009-01-05 14:47
            @隔葉黃鶯
            例如:
            Class Service {
            protected final LogFactory.getLog(this.getClass());
            }

            Class ServiceA extends Service {
            public void foo("foo");
            }

            Class ServiceB extends ServiceA{
            public void bar("bar");
            }

            這種情況,如果ServiceB的實例調用了foo的日志,LOG輸出的類是ServiceB,而不是ServiceA,但是我們需要分析問題時,需要的是ServiceA,配置文件也是應該配在ServiceA上的。
              回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            3220
            Posted @ 2009-01-05 18:34
            我認為spring 的作者使用“private final Log LOG = ...”其中的變量名是全部大寫的,而不使用常見的 log, logger 等等,也許就是因為他不希望應用的開發者重名。沒有人禁止你定義 static 的 logger.

            純粹感覺:只要加了 final ,編譯器便可以進行更多優化。
            純粹感覺:spring是久經考驗的框架,他這樣用也許有我們還沒有考慮到的問題。


              回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            隔葉黃鶯
            Posted @ 2009-01-06 08:39
            @溫少的日志
            看看你的 log4j.properties 中的
            layout.ConversionPattern
            是怎么寫的,看能否有所改進?  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            溫少的日志
            Posted @ 2009-01-06 11:28
            @隔葉黃鶯
            log4j.properties文件中,layout.ConversionPattern一般都是%c或者%c{1}來顯示類名,你還能怎么配?  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            3220
            Posted @ 2009-01-06 14:42
            log4j 還可以配置 %F:文件名,%L 行號  回復  更多評論   
          • # re: 也說一種普遍錯誤使用的LOG方式
            溫少的日志
            Posted @ 2009-01-06 15:37
            @3220
            使用%F解決了輸出格式問題,但是LOG Leval的配置還是按照類別來區分,問題還是依然存在的。  回復  更多評論   

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
           
          主站蜘蛛池模板: 左贡县| 望城县| 印江| 策勒县| 江陵县| 南投市| 卫辉市| 溧水县| 石台县| 滨海县| 贵德县| 常熟市| 盐山县| 夏河县| 扶沟县| 滨海县| 道孚县| 宜兴市| 沙坪坝区| 龙南县| 应用必备| 义马市| 隆回县| 类乌齐县| 遵化市| 武宁县| 林芝县| 专栏| 额济纳旗| 四平市| 无锡市| 镶黄旗| 辽宁省| 怀来县| 花莲县| 海南省| 永修县| 鹿泉市| 九寨沟县| 剑河县| 株洲县|