以前一直在使用System.out.println()來調試.可是用這種方式開發項目部署到生產環境,會由於衆多的控制檯輸出下降應用的性能.這時候Log4J就成爲可平衡開發和部署應用的利器了.java
在項目中使用Log4J並非一件困難的事情,簡單粗暴的方式就是在每一個類A中聲明一個Logger私有屬性apache
private static Logger logger = Logger.getLogger(A.class);
這樣雖然簡單,可是帶來有兩個問題:app
1.增長系統開銷-每一個使用Log4J的類都增長了對象屬性.性能
2.麻煩:每一個使用Logger的類都要重複聲明上面Logger對象.測試
其實不難發現可使用重構手法,聲明一個公用的類Log4jUtils,處理Logger的公共操做.spa
不過呢,問題不這麼簡單.首先要解決一個問題,Logger.getLogger(A.class)中的A.class有什麼用?A.class能夠不能夠瞎寫?debug
先作個試驗,先簡單配置log4j.properties文件調試
#日誌級別,輸出目的地 log4j.rootLogger=debug,stdout log4j.appender.stdout=org.apache.log4j.Conso leAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%c %d{ABSOLUTE} %5p %c{1}:%L - %m%n日誌
測試類code
import org.apache.log4j.Logger; /** * Created by li on 2015/5/24. */ public class LoggerTest { private static Logger logger = Logger.getLogger(Object.class); public static void main(String[] args) { logger.debug("Hello World!"); } }
查看結果:
結合log4j.properties配置的
log4j.appender.stdout.layout.ConversionPattern=%c %d{ABSOLUTE} %5p %c{1}:%L - %m%n
不難知道%c輸出所屬的類目,一般就是所在類的全名。可是咱們追蹤的實際上是LoggerTest類,結果返回的倒是java.lang.Object,簡直就是誤導(雖然能夠瞎寫,可是不建議,由於咱們可能須要知道輸入日誌的類是哪一個).
這時候將LoggerTest類的代碼修改
private static Logger logger = Logger.getLogger(LoggerTest.class);
運行結果變爲:
要的結果終於出現了.至此,明白了getLogger(class)的參數用途:追蹤產生此日誌的類.
如今就出現了新的問題:若要使用一個類Log4jUtils來專門處理Logger對象的聲明等操做,那麼如何處理getLogger(class)的參數問題?
也就是如何在Log4jUtils獲得調用logger對象的類型.
解決這個困難能夠是使用Java的反射機制
看下面的代碼:
/** * Created by li on 2015/5/23. */ public class Log4JUtils{ private static Logger logger = null; public static Logger getLogger(){ if (null == logger){ //Java8 廢棄了Reflection.getCallerClass() logger = Logger.getLogger(Reflection.getCallerClass().getName()); logger.debug("調用者類名"+Reflection.getCallerClass().getName()); } return logger; } }
修改類LoggerTest的代碼:
/** * Created by li on 2015/5/24. */ public class LoggerTest { // private static Logger logger = Logger.getLogger(LoggerTest.class); public static void main(String[] args) { Log4JUtils.getLogger().debug("Hello World!"); } }
運行結果:
看到這個結果就很爽了.之後項目就能夠放棄使用System.out.println()打印語句了.
log4j中的Logger.getLogger()能夠不用加載一個類,也能夠傳字符串的,這是一種通用作法,好比
Logger logger = Logger.getLogger("com.MyLog");
logger.info("...");
那麼Logger首先會去找log4j.properties中的log4j.category.com.MyLog對應的Appender來寫日誌,固然若是你配置了rootAppender的話不用配其餘的Appender也不要緊。
示例:
/** * @Author xiayuxuanmin * @Date 2019/8/10 * @Description */ public class LoggerTest { private static Logger logger = Logger.getLogger("myLog"); public static void main(String[] args) { logger.info("我是日誌"); } }
控制檯輸出:
由上可知:能夠直接在getLogger()方法中傳入一個string類型的字符串,那麼就能夠省去類的開銷(這裏也能夠瞎寫的,可是最好和當前類保持一致,這樣在看日誌的時候能夠知道是哪一個類產生的日誌...)