Java日志学习四:Simple Logging Facade for Java (SLF4J)源码浅析

一.SLF4J

     http://www.slf4j.org/

 

二.SLF4J核心类

  1.  Logger:日志类。
  2. LoggerFactory:负责查找系统里日志的实现,负责创建日志。类似JCL的LogFactory,类似log4j的LogManager。
  3. ILoggerFactory:该接口只有一个getLogger(name)方法。类似log4j的LoggerRepository 。
  4. LoggerFactoryBinder:该接口可以ILoggerFactory getLoggerFactory()。累世log4j的RepositorySelector。
  5. StaticLoggerBinder:实现LoggerFactoryBinder接口。LoggerFactory在查找日志的实现时,会调用StaticLoggerBinder的getSingleton()方法来判断系统里存在的日志实现。

三.Logger初始化

  1. LoggerFactory的getILoggerFactory方法首先执行performInitialization()。
    1. performInitialization调用bind()完成最核心的一段代码:静态查找日志实现类。怎么做的,StaticLoggerBinder.getSingleton(),就这么简单,如果没有异常说明找到了日志实现类,设置INITIALIZATION_STATE为SUCCESSFUL_INITIALIZATION;如果有异常,根据异常信息设置INITIALIZATION_STATE,如果是java.lang.ClassNotFoundException: org.slf4j.impl.StaticLoggerBinder,设置INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;找不到方法异常设置INITIALIZATION_STATE = FAILED_INITIALIZATION。
    2. bind()返回后,performInitialization()方法会再做一些版本检查,即StaticLoggerBinder可以定义一个静态的REQUESTED_API_VERSION字段,表示该StaticLoggerBinder支持的SLF4J版本,如果该版本不在LoggerFactory定义的兼容版本列表中(API_COMPATIBILITY_LIST),SLF4J会打印警告信息,并列出当前LoggerFactory兼容的版本列表。
  2. 执行完performInitialization后根据INITIALIZATION_STATE,返回对应ILoggerFactory实例。如果为SUCCESSFUL_INITIALIZATION返回绑定的StaticLoggerBinder中的ILoggerFactory实例;如果为NOP_FALLBACK_INITIALIZATION(没有找到桥接jar),则返回NOPLoggerFactory,它返回一个单例的NOPLogger实例,该类不会打印任何日志;如果初始化状态为FAILED_INITIALIZATION,抛出IllegalStateException异常;如果初始化状态为ONGOING_INITIALIZATION,则返回SubstituteLoggerFactory类实例,该状态发生在一个线程正在初始化LoggerFactory,而另一个线程已经开始请求获取ILoggerFactory实例,SubstituteLoggerFactory会记录当前请求的Logger名称,然后返回NOPLogger实例。所有这些在LoggerFactory初始化时被忽略的Logger Name会在LoggerFactory初始化成功以后被report出来(在System.err流中打印出来)。
    Java代码   收藏代码
    1. public static ILoggerFactory getILoggerFactory() {  
    2.     if (INITIALIZATION_STATE == UNINITIALIZED) {  
    3.       INITIALIZATION_STATE = ONGOING_INITIALIZATION;  
    4.       performInitialization();  
    5.     }  
    6.     switch (INITIALIZATION_STATE) {  
    7.       case SUCCESSFUL_INITIALIZATION:  
    8.         return StaticLoggerBinder.getSingleton().getLoggerFactory();  
    9.       case NOP_FALLBACK_INITIALIZATION:  
    10.         return NOP_FALLBACK_FACTORY;  
    11.       case FAILED_INITIALIZATION:  
    12.         throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);  
    13.       case ONGOING_INITIALIZATION:  
    14.         // support re-entrant behavior.  
    15.         // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106  
    16.         return TEMP_FACTORY;  
    17.     }  
    18.     throw new IllegalStateException("Unreachable code");  
    19.   }  
     
  3. 得到ILoggerFactory后调用ILoggerFactory.getLogger(name)返回Logger实例。如果使用slf4j作为日志实现,则得到一个org.slf4j.impl.SimpleLogger = org.slf4j.impl.SimpleLoggerFactory.getLogger(name)。SimpleLogger 定义了五个日志级别:TRACEDEBUGINFOWARNERROR。SimpleLogger还支持对classpath下的simplelogger.properties配置文件的解析,不过我们好像基本没用到这个。根据以往的经验,都是先从系统属性里查找这些属性,找不到再去simplelogger.properties查找,当然,SimpleLogger 就是这么做的。
    Java代码   收藏代码
    1. public static final String SYSTEM_PREFIX = "org.slf4j.simpleLogger.";  
    2.   
    3. public static final String DEFAULT_LOG_LEVEL_KEY = SYSTEM_PREFIX + "defaultLogLevel";  
    4. public static final String SHOW_DATE_TIME_KEY = SYSTEM_PREFIX + "showDateTime";  
    5. public static final String DATE_TIME_FORMAT_KEY = SYSTEM_PREFIX + "dateTimeFormat";  
    6. public static final String SHOW_THREAD_NAME_KEY = SYSTEM_PREFIX + "showThreadName";  
    7. public static final String SHOW_LOG_NAME_KEY = SYSTEM_PREFIX + "showLogName";  
    8. public static final String SHOW_SHORT_LOG_NAME_KEY = SYSTEM_PREFIX + "showShortLogName";  
    9. public static final String LOG_FILE_KEY = SYSTEM_PREFIX + "logFile";  
    10. public static final String LEVEL_IN_BRACKETS_KEY = SYSTEM_PREFIX + "levelInBrackets";  
    11. public static final String WARN_LEVEL_STRING_KEY = SYSTEM_PREFIX + "warnLevelString";  
     

 

三.定义自己的日志实现

     如果我们想以slf4j作为门面,实现一个自己的日志系统,我们需要一下三点,就这么简单。

  1. MyLogger implements  org.slf4j.Logger。
  2. MyFactory implements org.slf4j.ILoggerFactory。重写MyLogger getLogger()方法。
  3. StaticLoggerBinder implements org.slf4j.spi.LoggerFactoryBinder,这里名称必须是StaticLoggerBinder ,并且提供static getSingleton()方法,并且getLoggerFactory()方法里返回MyFactory 。

      看看log4j是怎么做的。参考slf4j-log4j12-1.7.5.jar源码。slf4j-log4j12-1.7.5.jar pom会依赖log4j。

  1. org.apache.log4j.Logger log4jLogger已经存在。
  2. Log4jLoggerFactory implements org.slf4j.ILoggerFactory。重写了org.apache.log4j.Logger getLogger()方法。返回的是包装了log4jLogger的一个Log4jLoggerAdapter。new Log4jLoggerAdapter(log4jLogger)。
  3. StaticLoggerBinder implements org.slf4j.spi.LoggerFactoryBinder,getLoggerFactory()方法返回Log4jLoggerFactory 。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值