`
macken
  • 浏览: 346908 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

slf4j源码分析

    博客分类:
  • Java
 
阅读更多

近期由于想利用应用程序的输出日志做一些应用,了解了下java的log框架,先说slf4j,slf4j用来做什么的呢?官网解释

     

     The Simple Logging Facade for Java or (SLF4J) serves as a simple facade or abstraction for various logging frameworks, e.g. java.util.logging, log4j and logback, allowing the end user to plug in the desired logging framework at deployment time

slf4j为不同的日志框架提供统一的日志接口,在编译时即将绑定了相应的日志框架(静态绑定)。slf4j的好处自行百度。

 

slf4j的源码结构分为三部分

1.原有日志接口到slf4j的桥接包 如jcl-over-slf4j,jul-to-slf4j;

2.slf4j到各个日志框架桥接包,如slf4j-log12,slf4j-jdk14;

3.slf4j-api 核心api包,对外提供统一接口;

 

主要分析slf4j-api的实现,后续以slf4j+log4j、slf4j+logback举例说明

 

 

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestLog {
	public static final Logger logger=LoggerFactory.getLogger(TestLog.class);
	public static void main(String[] args) {
		logger.info("{}","macken");
	}
}

 

 常用使用方式,如上代码所示

slf4j-api提供了Logger(接口)、LoggerFacotry(类)

LoggerFactory的getLogger方法

 

public static Logger getLogger(String name) {
    ILoggerFactory iLoggerFactory = getILoggerFactory();
    return iLoggerFactory.getLogger(name);
  }

 

 调用getILoggerFactory获得一个实现了ILoggerFactory接口的对象,查看getILoggerFactory方法

 

public static ILoggerFactory getILoggerFactory() {
    if (INITIALIZATION_STATE == UNINITIALIZED) {
      INITIALIZATION_STATE = ONGOING_INITIALIZATION;
      performInitialization();
    }
    switch (INITIALIZATION_STATE) {
      case SUCCESSFUL_INITIALIZATION:
        return StaticLoggerBinder.getSingleton().getLoggerFactory();
      case NOP_FALLBACK_INITIALIZATION:
        return NOP_FALLBACK_FACTORY;
      case FAILED_INITIALIZATION:
        throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
      case ONGOING_INITIALIZATION:
        // support re-entrant behavior.
        // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
        return TEMP_FACTORY;
    }
    throw new IllegalStateException("Unreachable code");
  }

 switch前的一通检查,检查是否存在StaticLoggerBinder类,是否存在几个,如果状态是SUCCESSFUL_INITIALIZATION,则调用StaticLoggerBinder.getSingleton().getLoggerFactory()

通过这个方法实现静态绑定,StaticLoggerBinder的实现不同的日志框架实现不同,返回的LoggerFacotry必须实现了ILoggerFactory接口;

 

以log4j的桥接包slf4j-log4j12的实现为例

 

其中Log4jLoggerFactory定义

 

public class Log4jLoggerFactory implements ILoggerFactory {

  // key: name (String), value: a Log4jLoggerAdapter;
  Map loggerMap;
}

 

 StaticBinderLogger定义(只提取了部分代码)

 

 

public class StaticLoggerBinder implements LoggerFactoryBinder {

	private final ILoggerFactory loggerFactory;

	private StaticLoggerBinder() {
		loggerFactory = new Log4jLoggerFactory();
		try {
			Level level = Level.TRACE;
		} catch (NoSuchFieldError nsfe) {
			Util.report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
		}
	}

	public ILoggerFactory getLoggerFactory() {
		return loggerFactory;
	}

}

 

 

StaticBinderLogger、Log4jLoggerFactory都是单例模式,StaticBinderLogger获取一个Log4jLoggerFactory,它实现了ILoggerFactory接口,Log4jLoggerFactory维护一个loggerMap,保证同名的logger只创建一次,根据传入的logger名返回对应的Logger,由于Log4j的Logger对象与slf4j的Logger接口不完全相同,需要在Log4j的Logger对象上进行一层封装,因此使用了Log4jLoggerAdapter,getLogger代码

 

public Logger getLogger(String name) {
    Logger slf4jLogger = null;
    // protect against concurrent access of loggerMap
    synchronized (this) {
        slf4jLogger = (Logger) loggerMap.get(name);
      if (slf4jLogger == null) {
        org.apache.log4j.Logger log4jLogger;
        if(name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME)) {
           log4jLogger = LogManager.getRootLogger();
        } else {
          log4jLogger = LogManager.getLogger(name);
        }
        slf4jLogger = new Log4jLoggerAdapter(log4jLogger);
        loggerMap.put(name, slf4jLogger);
      }
    }
    return slf4jLogger;
  }

slf4j+log4j使用的pom配置

 

<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.1</version>
		</dependency>

 

 可能是由于slf4j的作者同时也是log4j的作者觉得slf4j与log4j搭档起来不是很和谐,或者log4j性能比较挫,就写了一个slf4j的完全实现logback,性能也提高了不少

值得一提的是Log4jLoggerFactory使用的是HashMap存储logger对象,而在logback中的factory类LoggerContext使用HashTable存储logger对象,所以使用slf4j+log4j使用时不时线程安全的。

logback的pom配置直接引入就可以,内置包含slf4j-api包

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2
1
分享到:
评论
2 楼 kyfxbl 2012-12-11  
slf4j只是一个facade,值得研究的点不多。真要研究日志框架的源码,可以看一下logback和commons-logging
1 楼 wxl24life 2012-12-11  
感谢。最近也在看源码,正在琢磨用什么方式记录源码分析的过程。

引用
一点小建议
StaticBinderLogger定义(只提取了部分代码)


既然提取部分代码,至少关键的细节不要漏掉
建议补全 getSingleton() 方法的实现

相关推荐

    slf4j-log4j12 等jar包.rar

    综上所述,"slf4j-log4j12.jar"是连接SLF4J接口和Log4j 1.2日志系统的桥梁,常用于Java项目的日志处理,尤其在与DBUnit这样的测试框架配合时,能提供详细的测试日志,帮助开发者分析测试结果和定位问题。同时,掌握...

    基于Java平台的日志API统一接口SLF4J设计源码分析

    本项目是针对Java平台的日志API统一接口SLF4J的设计源码分析,项目包含361个文件,涵盖263个Java源文件、23个XML配置文件、18个JAR包文件、17个TXT文件、13个HTML文件、9个属性文件、4个YAML文件、4个SLF4J ...

    slf4j 1.5.0 源码

    3. **日志适配器**:SLF4J提供了一系列适配器,如`log4j-over-slf4j.jar`,将Log4j的日志调用转发到SLF4J接口,允许在使用Log4j的项目中无缝集成SLF4J。 4. **API扩展**:除了基本的日志方法,SLF4J还提供了`Marker...

    调试日志之slf4j+logback

    本文将深入探讨“调试日志之slf4j+logback”的主题,这两个组件是Java开发中的常见日志解决方案。 SLF4J(Simple Logging Facade for Java)是一个日志门面,它为各种日志框架提供了统一的接口,如Log4j、Logback等...

    slf4j-android

    SLF4J(Simple Logging Facade for Java)是Java平台上的一种日志抽象层,它为各种日志框架,如Log4j、Logback等提供一个简单的接口...通过源码分析和自定义修改,开发者可以进一步优化日志系统,使其更符合项目需求。

    slf4j使用和源码分析

    #### 四、SLF4J 源码分析 SLF4J 的核心设计在于其简单而强大的 API 设计以及灵活的日志框架选择机制。具体来说: 1. **API 设计**:SLF4J 的 API 设计简洁明了,通过 `Logger` 接口提供了 `debug()`, `info()`, `...

    Spring Boot SLF4J日志实例 / Logback

    **Spring Boot SLF4J与Logback日志实践** 在Java开发中,日志系统扮演着至关重要的角色,它能够帮助我们追踪程序运行时的问题、分析性能瓶颈以及调试代码。Spring Boot作为现代化的Java开发框架,已经为我们预设了...

    slf4j+logback

    SLF4J(Simple Logging Facade for Java)和Logback是Java日志处理中的两个重要组件,...通过对SLF4J接口的使用和Logback的细致配置,开发者可以更好地监控和分析应用程序的行为,同时保持代码的可移植性和可维护性。

    slf4j-1.6.1.rar

    SLF4J的1.6.1版本是一个重要的发布,包含了文档、源码和jar包,方便开发者深入理解和使用这个库。 首先,让我们详细了解SLF4J的基本概念。SLF4J的主要目标是为各种日志框架(如Log4j、Logback等)提供一个统一的...

    slf4j中的MDC

    了解以上知识点后,你可以更有效地利用SLF4J的MDC特性来提升你的日志系统,便于追踪问题和分析日志。在实际项目中,配合源码阅读和工具使用,如查看博客文章(如提供的链接),可以帮助你更深入地理解和运用这一功能...

    slf4j-1.5.8.rar Hibernate日志接口

    5. **Source Code**:如果包含源码,开发者可以查看内部实现,更深入地学习SLF4J的工作原理。 在Hibernate中,日志接口通常会使用SLF4J。为了配置Hibernate使用SLF4J,你需要在Hibernate的配置文件(如`hibernate....

    log4j logback slf4j

    本文将深入探讨三个重要的Java日志框架——Log4j、Logback和SLF4J,并分析它们之间的关系和使用场景。 **Log4j** Log4j是Apache组织的一个开源项目,是Java世界中最先广泛使用的日志记录框架之一。它的核心功能...

    slf4j-1.6.4.tar.gz

    `slf4j-1.6.4.tar.gz`是一个压缩包文件,包含了SLF4J版本1.6.4的源码、库文件和其他相关资源。 **SLF4J的核心概念:** 1. **接口层**:SLF4J提供了一组API接口,如`Logger`, `LocationAwareLogger`等,供开发者在...

    基于Java语言的slf4j日志框架设计源码分析与应用

    本项目深入分析了基于Java语言的SLF4J日志框架设计源码,涉及357个文件,涵盖259个Java源文件、23个XML配置文件、18个JAR包文件、17个文本文件、13个HTML文件、9个属性文件、4个YAML文件以及少量其他类型文件。...

    日志框架统一输出控制(slf4j+log4j)

    将SLF4J与Log4j结合使用,首先需要在项目中引入SLF4J的API库和Log4j的实现库。在`pom.xml`文件中,添加如下依赖: ```xml &lt;groupId&gt;org.slf4j &lt;artifactId&gt;slf4j-api &lt;version&gt;1.7.30 &lt;groupId&gt;org....

    slf4j-rabbitmq:SLF4J绑定,用于通过AMQP将日志消息发布到RabbitMQ服务器

    结合这两个技术,`slf4j-rabbitmq` 提供了一个桥梁,使得应用能够通过SLF4J接口将日志消息发布到RabbitMQ服务器,从而实现了日志的集中管理和分析。 在Java开发中,使用SLF4J的优势在于其灵活性。SLF4J提供了一个...

    slf4j+logback 于log4j+commons-logging大PK

    SLF4J通过`slf4j-api.jar`提供API,而具体的日志实现则通过相应的桥接器(如`log4j-over-slf4j.jar`)来实现。 Logback则是由Log4j的创始人Ceki Gülcü设计的一个更现代、更高效的日志系统。它被设计为比Log4j更快...

    log4j2+slf4j+spring4+mybatis的整合使用

    与log4j2紧密集成的log4j-slf4j-bridge模块,使log4j2可以作为SLF4J的实现,允许应用程序使用SLF4J API进行日志记录,同时使用log4j2作为后端。这样,应用程序可以享受到log4j2的高性能和灵活性,同时又可以利用SLF4...

    spring mvc-3.1.1与logback-1.0.3,slf4j-1.6.4集成

    总之,Spring MVC与Logback和SLF4J的集成提供了一种高效、可维护的日志解决方案,使得开发者在处理复杂Web应用时,能够方便地跟踪和分析运行时信息,从而提高问题定位和故障排查的效率。通过自定义的配置类和配置...

    SLF4JTest:这是一个示例程序,可通过SLF4J + Logback输出日志。

    解压后,通过查看源码和配置文件,可以进一步了解该项目如何使用SLF4J和Logback来实现日志记录。学习和理解这些内容对于任何Java开发者来说都是至关重要的,因为它有助于调试、监控和分析应用程序的行为。

Global site tag (gtag.js) - Google Analytics