02.日志框架组合

这篇博客详细介绍了如何将SLF4J与logback、log4j2结合使用。首先,解释了slf4j+logback的结合,包括引入依赖、获取日志工厂和日志对象的过程。接着,讨论了slf4j+log4j2的组合,强调了它们之间的区别,如日志工厂绑定和获取日志对象的方式。内容深入到各个框架的核心组件,如StaticLoggerBinder、LoggerContext和LogManager,展示了日志初始化和配置加载的机制。
摘要由CSDN通过智能技术生成

日志框架组合

slf4j+logback

引入依赖

    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${
   slf4j.version}</version>
      <scope>compile</scope>
    </dependency>
  • slf4j-api提供日志门面抽象,包括
    • LoggerFactoryBinder:日志工厂绑定抽象
    • ILoggerFactory:日志工厂抽象
    • Logger:日志抽象
  • logback-classic提供
    • StaticLoggerBinder:日志工厂绑定实现
    • LogContext:日志工厂实现
    • Logger:日志实现
    • ContextInitializer:日志工厂初始化
  • logback-core提供
    • 日志工厂初始化相关配置

slf4j通过如下方式调用,项目中可直接使用,jcl-over-slf4j和spring-jcl中最终也是调用此方法将日志转换到slf4j

    private static Logger log = LoggerFactory.getLogger(TestController.class);
  • getLogger(String name)

getLogger(String name)是具体执行 的方法,一共分两步:

  1. 获取日志工厂;

  2. 从日志工厂获取log对象并返回。

    ILoggerFactory是slf4j提供的日志工厂类接口标准,支持slf4j门面的日志框架需要实现此接口

public final class LoggerFactory {
   
 	public static Logger getLogger(String name) {
   
        #获取日志工厂
        ILoggerFactory iLoggerFactory = getILoggerFactory();
        #获取日志类
        return iLoggerFactory.getLogger(name);
    }
}

获取日志工厂

getILoggerFactory()主要的作用是执行日志工厂绑定,将slf4j门面和具体的日志实现进行绑定

public final class LoggerFactory {
   
    
    static final int UNINITIALIZED = 0;
    static final int ONGOING_INITIALIZATION = 1;
    static final int FAILED_INITIALIZATION = 2;
    static final int SUCCESSFUL_INITIALIZATION = 3;
    static final int NOP_FALLBACK_INITIALIZATION = 4;

    static volatile int INITIALIZATION_STATE = UNINITIALIZED;
    
    public static ILoggerFactory getILoggerFactory() {
   
        #如果状态是未初始化,执行初始化
        if (INITIALIZATION_STATE == UNINITIALIZED) {
   
            synchronized (LoggerFactory.class) {
   
                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://jira.qos.ch/browse/SLF4J-97
            return SUBST_FACTORY;
        }
        throw new IllegalStateException("Unreachable code");
    }
}

LoggerFactory中定义了5种状态,分别为

  1. UNINITIALIZED = 0;未初始化
  2. ONGOING_INITIALIZATION = 1;正在初始化
  3. FAILED_INITIALIZATION = 2;初始化失败
  4. SUCCESSFUL_INITIALIZATION = 3;初始化成功
  5. NOP_FALLBACK_INITIALIZATION = 4;

同时使用INITIALIZATION_STATE记录当前状态,初始状态为INITIALIZATION_STATE=UNINITIALIZED,随着方法执行,状态随之流转。首次调用方法,状态变更INITIALIZATION_STATE=ONGOING_INITIALIZATION,同时执行performInitialization()方法执行初始化

  • performInitialization()

performInitialization()主要的作用是执行绑定和版本兼容性检查,检查绑定的日志门面的版本和日志实现的版本是否能够匹配

public final class LoggerFactory {
   
    private final static void performInitialization() {
   
        #绑定具体日志框架实现
        bind();
        if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
   
            #版本兼容性检查
            versionSanityCheck();
        }
    }
}
  • bind()

bind()的核心是StaticLoggerBinder.getSingleton(),用来和日志实现框架进行绑定,实现slf4j门面的日志框架需要提供 org.slf4j.impl.StaticLoggerBinder类 ,如果项目中同时引用了多个StaticLoggerBinder,根据pom文件中的顺序决定使用哪个,最上面的优先使用

public final class LoggerFactory {
   
	private final static void bind() {
   
        try {
   
            Set<URL> staticLoggerBinderPathSet = null;
            // skip check under android, see also
            // http://jira.qos.ch/browse/SLF4J-328
            #判断是否是安卓系统
            if (!isAndroid()) {
   
                #找出所有包含org/slf4j/impl/StaticLoggerBinder.class的类
                staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
                #如果有多个,输出报告都是谁
                reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
            }
            // the next line does the binding
            #核心方法,真正执行绑定
            StaticLoggerBinder.getSingleton();
            #状态变更为初始化成功
            INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
            #如果有多个,输出报告具体绑定了谁
            reportActualBinding(staticLoggerBinderPathSet);
            fixSubstituteLoggers();
            replayEvents();
            // release all resources in SUBST_FACTORY
            SUBST_FACTORY.clear();
        } catch (NoClassDefFoundError ncde) {
   
            String msg = ncde.getMessage();
            if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
   
                INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
                Util.report("Failed to load class \"org.s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值