SLF4J 中的适配器模式

什么是适配器模式

适配器模式中,适配器包装不兼容指定接口的对象,来实现不同兼容指定接口。

SLF4J 中的适配器模式

SLF4J 是一个日志门面系统,其中提供了统一的 Logger 等接口,许多框架都会面向 SLF4J 打印日志,这样就不会和具体的日志框架耦合在一起,框架使用者也就能够很方便地在不同日志实现之间切换。

SLF4J 出现之前,已经有 Log4j 等日志框架了,其本身有一套 Logger 之类的接口,为实现和 SLF4J 兼容,就引入了对应适配器层 slf4j-log4j12。

首先看一下 SLF4J 中的 Logger 接口:

public interface Logger {

    String getName();

    void debug(String msg);

    void info(String msg);
    
    void warn(String msg);

    void error(String msg);
    
    // ...省略其他方法
}

而待适配的 Log4j 的 Logger 部分源码如下:

public class Logger extends Category {

    protected Logger(String name) {
        super(name);
    }

    public static Logger getLogger(String name) {
        return LogManager.getLogger(name);
    }

    public static Logger getLogger(Class clazz) {
        return LogManager.getLogger(clazz.getName());
    }

    public static Logger getRootLogger() {
        return LogManager.getRootLogger();
    }

    public static Logger getLogger(String name, LoggerFactory factory) {
        return LogManager.getLogger(name, factory);
    }

    public void trace(Object message) {
        if (!this.repository.isDisabled(5000)) {
            if (Level.TRACE.isGreaterOrEqual(this.getEffectiveLevel())) {
                this.forcedLog(FQCN, Level.TRACE, message, (Throwable)null);
            }

        }
    }
    
    // ...省略部分方法
}

其继承的 Category 类中有 debug、info 等方法。其核心方法为 log:

public void log(String callerFQCN, Priority level, Object message, Throwable t) {
    if(repository.isDisabled(level.level)) {
      return;
    }
    if(level.isGreaterOrEqual(this.getEffectiveLevel())) {
      forcedLog(callerFQCN, level, message, t);
    }
}

下面再看适配器类 Log4jLoggerAdapter,它先是继承了 MarkerIgnoringBase,MarkerIgnoringBase 实现了 Logger,等于说 Log4jLoggerAdapter 实现了 Logger:

public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger, Serializable {

    private static final long serialVersionUID = 6182834493563598289L;

    final transient org.apache.log4j.Logger logger;

    Log4jLoggerAdapter(org.apache.log4j.Logger logger) {
        this.logger = logger;
        this.name = logger.getName();
        traceCapable = isTraceCapable();
    }

    public void debug(String msg) {
        logger.log(FQCN, Level.DEBUG, msg, null);
    }

    public void info(String msg) {
        logger.log(FQCN, Level.INFO, msg, null);
    }

    // ...省略部分方法
}

Log4jLoggerAdapter 的构造方法接收 org.apache.log4j.Logger 类型的对象,其 debug 等方法的实现中,将具体的打印工作委托给 Log4j Logger。

如果 Log4j 和 SLF4J 正常整合,则 SLF4J 的 LoggerFactory.getLogger 方法最终会返回 Log4jLoggerAdapter 的实例,从而使 Log4j 和 SLF4J 兼容。

下面是类图:

img

参考:slf4j 中有典型适配器模式,不看一看?

posted @ 2024-10-26 11:34  Higurashi-kagome  阅读(14)  评论(0编辑  收藏  举报