关于SLF4J结合Log4j使用时日志输出与指定的log4j.properties不同

1、出现的原因:log4j,slf4j结合使用时,这里说下slf4j的一点原理:它是facade模式设计的,简单的说它只是个门面,具体做事的还是被他包装起来的(如:apache common logging,log4j,jdklogging等),所以在搭建项目是如果想使用slf4j那你必须还得选择一个干活的工具,也就是对应的配置文件,这里我选者Log4j,相应的配置文件是log4j.properties.

 

2、为什么出错了:我在搭建工程的时候放了log4j-1.2.16.jar、slf4j-api-1.5.11.jar、slf4j-simple-1.5.11.jar,使用的配置文件是log4j.properties,用:

Java代码 复制代码  收藏代码
  1. PropertyConfigurator.configure("conf/log4j.properties");  
PropertyConfigurator.configure("conf/log4j.properties");

 加载了日志配置,在spring中打出的日志和log4j.properties指定的格式相同,但是我在自己的程序中输出日志时显示的格式和指定的不同,应为没有琢磨透,所以很晕,无解,后来单独建立个工程找出了问题所在。其实很简单:

slf4j-simple-1.5.11.jar就是Jdk Logging相关的jar,而Jdk logging系统默认有一个配置文件,在JAVA_HOME中,而JDk logging加载配置文件的时候有个优先顺序(自己去查),所以出现了日志输出不同的问题。

 

选择JDK自带的日志系统,则只需要将slf4j-api-1.5.10.jar和slf4j-jdk14-1.5.10.jar放置到classpath中即可,如果中途无法忍受JDK自带的日志系统了,想换成log4j的日志系统,仅需要用slf4j-log4j12-1.5.10.jar替换slf4j-jdk14-1.5.10.jar即可

 

应用举例

        我们先举个实际例子,让大家有个直观认识,建立一个简单测试类,如下:
  1. package chb.test.slf4j;  
  2. import org.slf4j.Logger;  
  3. import org.slf4j.LoggerFactory;  
  4. /** 
  5.  * @author chb 
  6.  * 
  7.  */  
  8. public class TestSlf4j {  
  9.         Logger log = LoggerFactory.getLogger(TestSlf4j.class);  
  10.           
  11.         public void testLog(){  
  12.                 log.info("this is a test log");  
  13.         }  
  14.         /** 
  15.          * @param args 
  16.          */  
  17.         public static void main(String[] args) {  
  18.                 TestSlf4j slf = new TestSlf4j();  
  19.                 slf.testLog();  
  20.         }  
  21. }  
package chb.test.slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author chb * */ public class TestSlf4j { Logger log = LoggerFactory.getLogger(TestSlf4j.class); public void testLog(){ log.info("this is a test log"); } /** * @param args */ public static void main(String[] args) { TestSlf4j slf = new TestSlf4j(); slf.testLog(); } } 
1>JDK自带的log输出
       首先,我们在classpath中加入slf4j-api-1.5.10.jar和slf4j-jdk14-1.5.10.jar两个包,然后运行main函数,输出信息如下:
[javascript] view plain copy print ?
  1. 2010-1-5 21:44:47 chb.test.slf4j.TestSlf4j testLog  
  2. 信息: this is a test log  
2010-1-5 21:44:47 chb.test.slf4j.TestSlf4j testLog 信息: this is a test log 
 2>slg4j提供的simple log
      然后,我们用 slf4j-simple-1.5.10.jar替换slf4j-jdk14-1.5.10.jar ,选择使用slf4j提供的simple log,输出信息如下:
[javascript] view plain copy print ?
  1. 0 [main] INFO chb.test.slf4j.TestSlf4j - this is a test log  
0 [main] INFO chb.test.slf4j.TestSlf4j - this is a test log 
 3>log4j日志输出
    再然后,我们再用slf4j-log4j12-1.5.10.jar替换slf4j-simple-1.5.10.jar(记得classpath也需要增加log4j依赖jar包),同时增加一个log4j.properties文件,内容如下:
[python] view plain copy print ?
  1. log4j.debug=true  
  2. log4j.rootLogger=DEBUG,stdout  
  3. log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
  4. log4j.appender.stdout.Target=System.out  
  5. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
  6. log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p - %m%n  
log4j.debug=true log4j.rootLogger=DEBUG,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p - %m%n 
 我们再稍微修改一下main函数,加载一下log4j.properties,如;
  1. public static void main(String[] args) {  
  2.         System.setProperty("log4j.configuration""log4j.properties");  
  3.         TestSlf4j slf = new TestSlf4j();  
  4.         slf.testLog();  
  5. }  
public static void main(String[] args) { System.setProperty("log4j.configuration", "log4j.properties"); TestSlf4j slf = new TestSlf4j(); slf.testLog(); } 
运行main函数,输出结果如下:
[javascript] view plain copy print ?
  1. log4j: Parsing for [root] with value=[DEBUG,stdout].  
  2. log4j: Level token is [DEBUG].  
  3. log4j: Category root set to DEBUG  
  4. log4j: Parsing appender named "stdout".  
  5. log4j: Parsing layout options for "stdout".  
  6. log4j: Setting property [conversionPattern] to [%d{ABSOLUTE} %5p - %m%n  ].  
  7. log4j: End of parsing for "stdout".  
  8. log4j: Setting property [target] to [System.out].  
  9. log4j: Parsed "stdout" options.  
  10. log4j: Finished configuring.  
  11. 22:01:40,831  INFO - this is a test log  
log4j: Parsing for [root] with value=[DEBUG,stdout]. log4j: Level token is [DEBUG]. log4j: Category root set to DEBUG log4j: Parsing appender named "stdout". log4j: Parsing layout options for "stdout". log4j: Setting property [conversionPattern] to [%d{ABSOLUTE} %5p - %m%n ]. log4j: End of parsing for "stdout". log4j: Setting property [target] to [System.out]. log4j: Parsed "stdout" options. log4j: Finished configuring. 22:01:40,831 INFO - this is a test log 
  原理介绍--静态绑定
        大家看到要使用哪种日志系统,只需要将对应的日志系统所需要的jar包文件(包括slf4j提供的jar包和日志系统自身依赖的jar包,例如:slf4j-log4j12-1.5.10.jar和log4j.1.2.jar)放入classpath即可,slf4j可以自动探测具体使用哪种日志系统,这种技术被称为静态绑定。
       在实际使用中,我们通过LoggerFactory.getLogger()获得logger,查看LoggerFactory的源代码会发现如下两点,
  • LoggerFactory通过StaticLoggerBinder.getSingleton().getLoggerFactory()获得LogFactory,然后再通过该LogFactory来获取logger的
  • 但是StaticLoggerBinder类并不在slf4j-api-1.5.10.jar中,分析与具体日志系统相关的jar包,会发现每个jar包都有一个StaticLoggerBinder类的实现(如slf4j-log4j12-1.5.10.jar、slf4j-simple-1.5.10.jar、slf4j-jdk14-1.5.10.jar均有StaticLoggerBinder类实现),这就很明白了,slf4j在启动时会动态到classpath中查找StaticLoggerBinder类,找到之后就可以生成对应日志系统的日志文件了。
    这里就有一个问题了,slf4j是如何将自己的通用日志格式转成不同的日志系统的格式的呢?
    我们再分析每个日志系统相关的源代码,会发现不同日志系统包都会有一个Adapter,用来在slf4j和不同日志系统之间做转换。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值