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