slf4j介绍以及与Log4j、Log4j2、LogBack整合方法

时间:2023-03-10 05:38:02
slf4j介绍以及与Log4j、Log4j2、LogBack整合方法

翻了一下百度和官网。这么介绍slf4j。

  slf4j 全称 Simple Logging Facade for Java,是日志框架的一种抽象,那么也就是说 slf4j 是不能单独使用的必须要有其他实现日志框架来配合使用,并且如果要启用slf4j框架要导入slf4j-api-xxx.jar 这个包, 这个包是slf4j 实现各种支持的日志框架的包。比如log4j、log4j2、logback等。  slf4j也已经支持这几种日志组件。

  这里拿slf4j 和logback的整合使用为例,先来看依赖关系

  简单的从浅层源码来查找依赖关系

  通常我们在java类中使用日志要先拿到Logger,如:

  private static final Logger          LOGGER        = LoggerFactory.getLogger(Test.class);

  我们来看getLogger方法的代码,注意 getLogger 这个静态方法是属于 slf4j-api-xxx.jar的org.slf4j包下的。

public static Logger getLogger(Class<?> clazz) {
Logger logger = getLogger(clazz.getName());
if (DETECT_LOGGER_NAME_MISMATCH) {
Class<?> autoComputedCallingClass = Util.getCallingClass();
if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
autoComputedCallingClass.getName()));
Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
}
}
return logger;
}

继续看方法第一行 getLogger的代码

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

继续看getILoggerFactory方法

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");
}

注意看:StaticLoggerBinder.getSingleton().getLoggerFactory();    其中StaticLoggerBinder 类是 logback-classic-xxx.jar 包下的 并且实现了 slfj-api-xxx.jar包的 LoggerFactoryBinder接口。 也就是说在 slf4j-api-xxx.jar包下的 getILoggerFactory 方法中调用了logback-classic-xxx.jar 包的StaticLoggerBinder类中的方法并且 该类实现了slf4j-api-xxx.jar 中的 LoggerFactoryBinder接口。

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();
}

而在getLoggerContext()方法中  StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext)  这段代码传入的参数是LoggerContext 是logback-class-xxx.jar 包中的。 并且StatusPrinter类是 logback-core-xxx.jar包中的。

这样就形成了继承关系为:  logback-core-xxx.jar  -->  logback-classic-xxx.jar --> slf4j-api-xxx.jar --> 自己的代码。

可能有疑问是slf4j怎样知道与谁整合拿谁的LoggerFactory , 其实是通过不同的jar包来实现的。

  slf4j与log4j整合导入的jar包为

    1. slf4j-api.jar
    2. slf4j-log4j12.jar
    3. log4j.jar

  slf4j与log4j2整合导入的jar包为:

    1. slf4j-api.jar
    2. log4j-slf4j-impl.jar
    3. log4j-api.jar
    4. log4j-core.jar

  slf4j与logback整合导入的jar包为:

    1. slf4j-api.jar
    2. logback-core.jar
    3. logback-classic.jar

  所以这样当更换日志框架的时候 slf4j接口是不用动的,只需要换下对应的实现框架的包就可以了。并且代码不用更改。

本文纯属原创, 转载请注明出处!