`

读logback源码系列文章(二)——提供ILoggerFactory

阅读更多
上篇博客介绍了logback是怎么对接slf4j的,简言之,就是通过下面这行代码
return StaticLoggerBinder.getSingleton().getLoggerFactory();

slf4j委托具体实现框架的StaticLoggerBinder来返回一个ILoggerFactory,从而对接到具体实现框架上

这篇博客就接下来介绍一下,logback的StaticLoggerBinder类是怎么创建ILoggerFactory的



在图中可以看到,在logback里,ILoggerFactory的实现类是LoggerContext

logback的StaticLoggerBinder类实现了LoggerFactoryBinder接口,这个接口有两个方法
public interface LoggerFactoryBinder {

  /**
   * Return the instance of {@link ILoggerFactory} that 
   * {@link org.slf4j.LoggerFactory} class should bind to.
   * 
   * @return the instance of {@link ILoggerFactory} that 
   * {@link org.slf4j.LoggerFactory} class should bind to.
   */
  public ILoggerFactory getLoggerFactory();

  /**
   * The String form of the {@link ILoggerFactory} object that this 
   * <code>LoggerFactoryBinder</code> instance is <em>intended</em> to return. 
   * 
   * <p>This method allows the developer to intterogate this binder's intention 
   * which may be different from the {@link ILoggerFactory} instance it is able to 
   * yield in practice. The discrepency should only occur in case of errors.
   * 
   * @return the class name of the intended {@link ILoggerFactory} instance
   */
  public String getLoggerFactoryClassStr();
}

其中比较重要的是getLoggerFactory()方法,其实自定义的StaticLoggerBinder类不实现这个接口也是可以的,只要能保证提供getLoggerFactory()方法,并返回一个ILoggerFactory就可以了

下面就来具体地看看StaticLoggerBinder类的代码:

首先,该类必须有一个getSingleton()方法,来返回该类的单例
private static StaticLoggerBinder SINGLETON = new StaticLoggerBinder();

public static StaticLoggerBinder getSingleton() {
    return SINGLETON;
  }

以上代码用了比较简单的单例模式,提供getSingleton()方法是对接slf4j的强制要求

然后这个类用了一个static块来保证初始化
static {
    SINGLETON.init();
  }

void init() {
    try {
      try {
        new ContextInitializer(defaultLoggerContext).autoConfig();
      } catch (JoranException je) {
        Util.report("Failed to auto configure default logger context", je);
      }
      StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext);
      contextSelectorBinder.init(defaultLoggerContext, KEY);
      initialized = true;
    } catch (Throwable t) {
      // we should never get here
      Util.report("Failed to instantiate [" + LoggerContext.class.getName()
          + "]", t);
    }
  }

这个初始化方法init()里做了2件事

第一件事是委托ContextInitializer类对defaultLoggerContext进行初始化。这里如果找到了任一配置文件,就会根据配置文件去初始化LoggerContext,如果没找到,会使用默认配置。关于LoggerContext是怎么根据配置文件进行配置的,在后面的博客中介绍,这里先略过

第二件事是对ContextSelectorStaticBinder类进行初始化
public void init(LoggerContext defaultLoggerContext, Object key) throws ClassNotFoundException,
      NoSuchMethodException, InstantiationException, IllegalAccessException,
      InvocationTargetException  {
    if(this.key == null) {
      this.key = key;
    } else if (this.key != key) {
      throw new IllegalAccessException("Only certain classes can access this method.");
    }
    
    
    String contextSelectorStr = OptionHelper
        .getSystemProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR);
    if (contextSelectorStr == null) {
      contextSelector = new DefaultContextSelector(defaultLoggerContext);
    } else if (contextSelectorStr.equals("JNDI")) {
      // if jndi is specified, let's use the appropriate class
      contextSelector = new ContextJNDISelector(defaultLoggerContext);
    } else {
      contextSelector = dynamicalContextSelector(defaultLoggerContext,
          contextSelectorStr);
    }
  }

如果系统参数中配置了JNDI,这里会得到一个ContextJNDISelector,实际应用中,一般会得到一个DefaultContextSelector,并且把已经初始化完成的defaultLoggerContext传给新创建的这个DefaultContextSelector

经过上面的步骤,StaticLoggerBinder的init()方法就走完了,接下来就会调用到关键的getLoggerFactory()方法
public ILoggerFactory getLoggerFactory() {
    if (!initialized) {
      return defaultLoggerContext;
    }

    if (contextSelectorBinder.getContextSelector() == null) {
      throw new IllegalStateException(
          "contextSelector cannot be null. See also " + NULL_CS_URL);
    }
    return contextSelectorBinder.getContextSelector().getLoggerContext();
  }

可以看到,这里有2条分支,如果initialized是false,那么会直接返回defaultLoggerContext。否则就委托刚才提到的ContextSelectorStaticBinder返回一个ContextSelector(一般就是DefaultContextSelector),然后由ContextSelector来返回LoggerContext
public class DefaultContextSelector implements ContextSelector {

  private LoggerContext context;
  
  public DefaultContextSelector(LoggerContext context) {
    this.context = context;
  }
  
  public LoggerContext getLoggerContext() {
    return getDefaultLoggerContext();
  }

  public LoggerContext getDefaultLoggerContext() {
    return context;
  }
}

可以看到,代码有点绕,不过逻辑还是很清楚的

总结一下这个过程:
1、StaticLoggerBinder在加载的时候,会去读取配置文件,并根据配置文件对LoggerContext进行初始化
2、然后初始化ContextSelectorStaticBinder,在这个类内部new一个DefaultContextSelector,并把第一步中配置完毕的LoggerContext传给DefaultContextSelector
3、调用getLoggerFactory()方法,直接返回第一步中配置的LoggerContext,或者委托DefaultContextSelector类返回LoggerContext
  • 大小: 181.7 KB
分享到:
评论

相关推荐

    springboot、logback源码解读

    Spring Boot与Logback源码解读涉及了Spring Boot框架在启动过程中如何与Logback日志系统集成,以及Logback是如何进行初始化和配置的。下面将详细解读Logback和Spring Boot的相关知识点。 ### Logback初始化过程 ...

    logback-1.1.2源码包

    **logback-1.1.2源码包详解** ...总之,logback-1.1.2 的源码包为我们提供了深入了解这个强大日志框架的机会,通过学习,开发者可以提升日志管理能力,优化应用性能,并且有机会参与到开源社区的贡献之中。

    扩展logback将日志输出到Kafka实例源码

    标题"扩展logback将日志输出到Kafka实例源码"涉及的技术点主要集中在如何将Logback与Kafka集成,使得日志可以被有效地发送到Kafka集群。这个过程通常涉及到以下几个步骤: 1. **添加依赖**:首先,你需要在项目的...

    logback源代码

    rar包中包括:logback源代码,以及struts2的基础的页面跳转,logback虽然是开源的,但它依赖的jar包找全不也不容易,当然你也可以用Maven去下载是最好的喽。 你可以访问:...

    JAVA日志组件系列(二)logback1.0.13and sli4j1.7.5

    本篇文章将深入探讨的是JAVA日志组件中的一个经典组合——logback 1.0.13 和 SLF4J 1.7.5。这两者都是由Ceki Gülcü开发的,他是Java世界中著名的日志框架Log4j的创始人。SLF4J(Simple Logging Facade for Java)...

    logback相关jar包

    **Logback核心组件——logback-core-1.0.13.jar** `logback-core-1.0.13.jar`是Logback的基础组件,提供了日志记录的基本功能。这个JAR文件包括了日志事件的生命周期管理、日志级别定义、配置解析、Appender(输出...

    logback jms源码分析加用法小结

    《logback jms源码分析及用法小结》 在Java世界中,日志管理是每个项目不可或缺的一部分。Logback作为一款强大的日志框架,因其高效、灵活和可配置性而深受开发者喜爱。本文将重点探讨Logback如何集成JMS(Java ...

    logback类库.rar

    接下来,我们来看看logback的配置文件——`logback.xml`。这是logback配置的核心,通过它可以定义日志级别(TRACE、DEBUG、INFO、WARN、ERROR、OFF),设置日志输出的目标(控制台、文件、网络等),以及定制日志...

    logback所需jar包

    Logback还提供了一些工具,例如`logback-examples`项目中的示例代码,帮助用户了解如何配置和使用Logback。此外,`logback-test.xml`是通常用于测试环境的日志配置文件,而`logback.xml`则用于生产环境。配置文件中...

    logback日志配置demo

    Logback 提供了高效的日志记录能力,适用于各种规模的应用程序。本教程将详细介绍如何配置 logback 以实现日志记录,并探讨不同配置方式。 首先,`pom.xml` 文件是 Maven 项目的配置文件,它包含了项目的依赖信息。...

    Logback类库含logback.xml配置文件

    Logback 是为了提供更高效、更灵活的日志记录解决方案而设计的,它不仅继承了 Log4j 的优点,还解决了一些性能和可扩展性问题。在Java应用程序中,日志系统扮演着至关重要的角色,它帮助开发者调试代码,记录错误,...

    logback 1.2.3.zip

    标签中的"logback"三次出现,强调了这个主题的核心——Logback日志框架。"logback-access-1"可能是对Logback访问模块的简称。"logback-classic-"和"logback-core-1.2"分别代表Logback的经典日志实现和核心库,它们是...

    logback

    在IT领域,logback是一个广泛使用的日志记录框架,由Ceki Gülcü创建,它是log4j的后续项目,旨在提供更高的性能和更灵活的配置。Logback的主要目标是提高日志处理的效率,同时保持简单性和可配置性。它支持多种...

    logback下载 日志文件jar包

    Logback 是一款广泛使用的日志记录框架,由 Ceki Gülcü 创建,作为其先前作品 Log4j 的改进版。这个压缩包包含了实现 Logback 功能所需的几个关键组件,以及一个配置文件,使得用户能够方便地管理和记录应用程序的...

    logback.的jar包

    1. **logback-core**: 这是 Logback 的核心模块,提供了基本的日志处理机制,包括事件处理、配置解析以及 Appender 和 Layout 的接口定义。它为 logback-classic 和 logback-access 提供了底层支持。 2. **logback-...

    maven+spring+jetty+logback简单项目源码

    这个"maven+spring+jetty+logback简单项目源码"提供了一个基础框架,方便新手快速入门并实践这些技术。 首先,`Maven`是Apache开发的一个项目管理和综合工具,它通过一个项目对象模型(Project Object Model, POM)...

    Logback框架需要的3个jar包和logback.xml文件

    Logback 提供了高效、灵活的日志记录解决方案,支持多种日志级别,如DEBUG、INFO、WARN、ERROR等,帮助开发者调试程序、定位问题,并且能够方便地调整日志输出级别和格式。 1. **Logback 核心组件**: - **logback...

    logback动态日志配置 - 示例源码

    本文将深入探讨如何在 Logback 中实现动态日志配置,并提供一个具体的示例源码分析。** ### 1. Logback 概述 Logback 是一个高效且灵活的日志框架,旨在提高系统的性能。它提供了日志记录、日志管理和日志部署等...

    SpringBoot中自定义日志配置logback-spring.xml示例源码

    默认情况下,Spring Boot使用Logback作为其日志系统,因为Logback在性能上优于Log4j,并且与Spring框架有良好的集成。本教程将详细介绍如何在Spring Boot中自定义日志配置,特别是通过`logback-spring.xml`文件来...

    springmvc log4j2 logback 注解 jackson 日志脱敏实现源码

    本资源包含的是关于`SpringMVC`、`Log4j2`、`Logback`以及`Jackson`的日志脱敏实现源码,提供了多种实现方式,旨在帮助开发者在保障信息安全的同时,充分利用日志进行系统分析。 1. **基于正则表达式的日志脱敏实现...

Global site tag (gtag.js) - Google Analytics