为何建议使用SLF4J而不直接用log4J、logback的API

1,931 阅读2分钟

1.问题

这个问题是实习的时候发现公司使用的都是slf4j打印日志,而之前在实验室做项目的时候,打印日志都是直接使用功能log4j的API。一开始并没有特别关注,直到有次看码出高效,里面的日志规约强制要求使用SLF4J。

如上,强制规约,有利于维护各个类的日志处理方式统一。

2.SLF4J

SLF4J (Simple Loging Facade For Java)是一个日志抽象层,允许你使用任何一个日志系统,并且可以随时切换还不需要动到已经写好的程序。单独的slf4j是不能工作的,它必须搭配其他具体的日志实现方案,比如apache的org.apache.log4j.Logger,jdk自带的java.util.logging.Logger等等。

2.1 SLF4J和Log4J的关系

2.2 优点

  • 简洁的占位符使用 占位符(place holder),在代码中表示为“{}”的特性。

占位符是一个非常类似于在string的format()方法中的%s,因为它会在运行时被某个提供的实际字符串所替换。这不仅降低了你代码中字符串连接次数,而且还节省了新建的string对象

//common log 需要拼接
log.info("Set score " + score + " for Person " + p.getName() + " ok.");
//Slf4j 
logger.info("className method error:{},msg:{}",response.get("code"),response.get("message"));
  • 日志级别的判断:info error warn debug trace ...
logger.info();
logger.error();
logger.warn();

3.适配者模式

3.1 什么是适配者模式

blog.csdn.net/lovejavasma… 适配器是为目标寻找合适的类的方法或者对找到的方法进行改造(重写)从而完成方法的调用

  • 对象适配器依赖于对象组合

Target:目标接口,需要一个method2方法的实现

Adaptee:被适配者(可以是类或者接口),仅有一个method1方法

Adapter:适配器,实现了Target接口,并继承了Adaptee方法

demo参考:https://blog.csdn.net/caoxiaohong1005/article/details/53445968

3.2 slf4j的应用

1.getLogger

2.LoggerFactory

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

    public static Logger getLogger(Class clazz) {
        return getLogger(clazz.getName());
    }
    
 // ILoggerFactory接口
import org.slf4j.Logger;
public interface ILoggerFactory {
    Logger getLogger(String var1);
}
    

getILoggerFactory方法:不同getLogger方法 其所对应的实现类为Adapter

3.其一Adapter:Log4jLoggerFactory

实现ILoggerFactory接口中getLogger方法

public class Log4jLoggerFactory implements ILoggerFactory {
    ConcurrentMap<String, Logger> loggerMap = new ConcurrentHashMap();

    public Log4jLoggerFactory() {
    }

    public Logger getLogger(String name) {
        Logger slf4jLogger = (Logger)this.loggerMap.get(name);
        if(slf4jLogger != null) {
            return slf4jLogger;
        } else {
            org.apache.log4j.Logger log4jLogger;
            if(name.equalsIgnoreCase("ROOT")) {
                log4jLogger = LogManager.getRootLogger();
            } else {
                log4jLogger = LogManager.getLogger(name);
            }
            //创建一个log4j对象实例
            Log4jLoggerAdapter newInstance = new Log4jLoggerAdapter(log4jLogger);
            Logger oldInstance = (Logger)this.loggerMap.putIfAbsent(name, newInstance);
            return (Logger)(oldInstance == null?newInstance:oldInstance);
        }
    }
}

重要参考:blog.csdn.net/caoxiaohong…

4.总结

  • SLF4J可以动态选择不同的logger
  • SLF4J原理实现用到适配器模式,工厂模式、单例模式
  • 适配器模式的常见应用:通用代码的合并Adapter