commons-logging.jar 和 log4j.jar 的關系


在學習springmvc的時候下載了3.1的版本,導入jar包的時候發現commons-logging.jar log4j.jar 這兩個jar包

做項目一直都是開發二期,從沒關注過jar包的組合,以及項目的搭建思路,有感而想,真是失敗。。。

--------------------------------------------------------------------------------------------------------------------------------

通常是使用 apache 的 log4j 日志管理工具。然而,在項目中,我們經常會看到兩個 jar 包:commons-logging.jar 和 log4j.rar。為什么我們在使用 log4j 的同時還要引入 commons-logging.jar 呢,或者說不用 commons-logging.jar 可不可以,這兩者之間到底是怎么的一種關系呢?


       
作為記錄日志的工具,它至少應該包含如下幾個組成部分(組件):
        1. Logger
             記錄器組件負責產生日志,並能夠對日志信息進行分類篩選,控制什么樣的日志應該被輸出,什么樣的日志應該被忽略。它還有一個重要的屬性 - 日志級別。不管何種日志記錄工具,大概包含了如下幾種日志級別:DEBUG, INFO, WARN, ERROR 和 FATAL。
        2. Level
            日志級別組件。
        3. Appender
            日志記錄工具基本上通過 Appender 組件來輸出到目的地的,一個 Appender 實例就表示了一個輸出的目的地。
       4. Layout
            Layout 組件負責格式化輸出的日志信息,一個 Appender 只能有一個 Layout。

        我們再來看看 log4j.jar,打開 jar 包,我們可以看到 Logger.class(Logger),Level.class(Level), FileAppender.class(Appender), HTMLLayout.class(Layout)。其它的我們先忽略不看,這幾個字節碼文件正好是記錄日志必不可少的幾個組件。

        接下來看看 commons-logging 中的 org.apache.commons.logging.Log.java 源碼:

Java代碼 復制代碼 收藏代碼
  1. package org.apache.commons.logging;   
  2. public interface Log {   
  3.     public boolean isDebugEnabled();   
  4.     public boolean isErrorEnabled();   
  5.     public boolean isFatalEnabled();   
  6.     public boolean isInfoEnabled();   
  7.     public boolean isTraceEnabled();   
  8.     public boolean isWarnEnabled();   
  9.     public void trace(Object message);   
  10.     public void trace(Object message, Throwable t);   
  11.     public void debug(Object message);   
  12.     public void debug(Object message, Throwable t);   
  13.     public void info(Object message);   
  14.     public void info(Object message, Throwable t);   
  15.     public void warn(Object message);   
  16.     public void warn(Object message, Throwable t);   
  17.     public void error(Object message);   
  18.     public void error(Object message, Throwable t);   
  19.     public void fatal(Object message);   
  20.     public void fatal(Object message, Throwable t);   
  21. }  
package org.apache.commons.logging;
public interface Log {
    public boolean isDebugEnabled();
    public boolean isErrorEnabled();
    public boolean isFatalEnabled();
    public boolean isInfoEnabled();
    public boolean isTraceEnabled();
    public boolean isWarnEnabled();
    public void trace(Object message);
    public void trace(Object message, Throwable t);
    public void debug(Object message);
    public void debug(Object message, Throwable t);
    public void info(Object message);
    public void info(Object message, Throwable t);
    public void warn(Object message);
    public void warn(Object message, Throwable t);
    public void error(Object message);
    public void error(Object message, Throwable t);
    public void fatal(Object message);
    public void fatal(Object message, Throwable t);
}



        很顯然,只要實現了 Log 接口,它就是一個名副其實的 Logger 組件,也驗證了 Logger 組件具有日志級別的屬性。繼續看 commons-logging org.apache.commons.logging.impl 包下的幾個類的源碼片段:

Java代碼 復制代碼 收藏代碼
  1. package org.apache.commons.logging.impl;   
  2.   
  3. import org.apache.commons.logging.Log;   
  4. import org.apache.log4j.Logger;   
  5. import org.apache.log4j.Priority;   
  6. import org.apache.log4j.Level;   
  7. import ......   
  8.   
  9. public class Log4JLogger implements Log, Serializable {   
  10.     // 對 org.apache.commons.logging.Log 的實現   
  11.     ......   
  12. }   
  13.   
  14. ------------------------------------------------------------------   
  15.   
  16. package org.apache.commons.logging.impl;   
  17.   
  18. import org.apache.commons.logging.Log;   
  19. import java.io.Serializable;   
  20. import java.util.logging.Level;   
  21. import java.util.logging.Logger;   
  22.   
  23. public class Jdk14Logger implements Log, Serializable {   
  24.      // 對 org.apache.commons.logging.Log 的實現   
  25.     ......   
  26. }  
package org.apache.commons.logging.impl;

import org.apache.commons.logging.Log;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.apache.log4j.Level;
import ......

public class Log4JLogger implements Log, Serializable {
    // 對 org.apache.commons.logging.Log 的實現
    ......
}

------------------------------------------------------------------

package org.apache.commons.logging.impl;

import org.apache.commons.logging.Log;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Jdk14Logger implements Log, Serializable {
     // 對 org.apache.commons.logging.Log 的實現
    ......
}



        好了,分析到這里,我們應該知道,真正的記錄日志的工具是 log4j 和 sun 公司提供的日志工具。而 commons-logging 把這兩個(實際上,在 org.apache.commons.logging.impl 包下,commons-logging 僅僅為我們封裝了 log4j 和 sun logger)記錄日志的工具重新封裝了一遍(Log4JLogger.java 和 Jdk14Logger.java),可以認為 org.apache.commons.logging.Log 是個傀儡,它只是提供了對外的統一接口。因此我們只要能拿到 org.apache.commons.logging.Log,而不用關注到底使用的是 log4j 還是 sun logger。正如我們經常在項目中這樣寫:

Java代碼 復制代碼 收藏代碼
  1. // Run 是我們自己寫的類,LogFactory 是一個專為提供 Log 的工廠(abstract class)   
  2. private static final Log logger = LogFactory.getLog(Run.class);  
// Run 是我們自己寫的類,LogFactory 是一個專為提供 Log 的工廠(abstract class)
private static final Log logger = LogFactory.getLog(Run.class);



        既然如此,我們向構建路徑加了 commons-logging.jar 和 log4j.jar 兩個 jar 包,那我們的應用程序到底使用的 log4j 還是 sun logger 呢?我們能不能認為由於加了 log4j.jar 包,就認為系統使用的就是 log4j 呢?事實上當然不是這樣的,那我還認為我正在使用 jdk 而認為系統使用的是 sun logger 呢。使用 Spring 的朋友可以在 web.xml 中看到如下 listener 片段:

Xml代碼 復制代碼 收藏代碼
  1. <listener>  
  2.     <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>  
  3. </listener>  
<listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>



        這是由 Spring 為我們提供的實現了標准的 servlet api 中的 javax.servlet.ServletContextListener 接口,用於在 web 容器啟動時做一些初始化操作。我們逐層進入 Spring 的源碼,可以看到如下代碼:

Java代碼 復制代碼 收藏代碼
  1. Log4jConfigurer.initLogging(location, refreshInterval);  
Log4jConfigurer.initLogging(location, refreshInterval);



        終於找到了 org.springframework.util.Log4jConfigurer,這正是 log4j 提供給我們的初始化日志的類。至此,我們終於明白了我們系統的的確確使用的是 log4j 的日志工具。

        可是問題又來了,org.apache.commons.logging.Log 和 org.apache.log4j.Logger 這兩個類,通過包名我們可以發現它們都是 apache 的項目,既然如下,為何要動如此大的動作搞兩個東西(指的是 commons-logging 和 log4j)出來呢?事實上,在 sun 開發 logger 前,apache 項目已經開發了功能強大的 log4j 日志工具,並向 sun 推薦將其納入到 jdk 的一部分,可是 sun 拒絕了 apache 的提議,sun 后來自己開發了一套記錄日志的工具。可是現在的開源項目都使用的是 log4j,log4j 已經成了事實上的標准,但由於又有一部分開發者在使用 sun logger,因此 apache 才推出 commons-logging,使得我們不必關注我們正在使用何種日志工具。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM