Logback是JAVA中的一个老牌日志框架。第一个版本从2006年开始,至今已经迭代了十多年。不过logback最新的稳定版还是2017年的,好几年没更新了;logback的兄弟slf4j最新的稳定版也是2017年的,有点爽。而且logback的异步性能实在捉襟见肘,功能简单,配置繁琐。远不如Apache的新一代日志框架——Log4j2。目前Log4j2为王,其他日志框架不是对手。一个升级版,相比于它的老祖宗Log4j1.x,有了很大的提升,和logback相比,有了很大的提升。除了内部设计的调整外,主要升级有以下几点:简化配置更强大的参数格式化最夸张的异步性能在Log4j2中,分为API(log4j-api)和实现(log4j-core)**两个模块。API和slf4j是一个类型,属于日志抽象/门面,实现部分是Log4j的核心2.org.apache.logging.log4j?log4j-apiorg.apache.logging.log4j?log4j-core最强性能和最强的异步性能这个特性是Log4j2的最强点。log4j2在JAVA中目前的日志框架中,异步日志的性能是最高的,没有之一。再来看看几款日志框架的benchmark对比结果(log4j2官方测试结果):从图中可以看出,log4j2的异步(全异步,非混合模式)性能远超log4j1和logback。.压力越大,吞吐量的差距就越大。64线程测试下,log4j2的吞吐量达到了180w+/s,而logback/log4j1不到20w,相差近十倍。零GC(无垃圾)自版本2.6(2016)起,log4j2默认为零GC模式有效。什么是零GC?由于log4j2,它不会导致GC。log4j2中的各种Message对象、字符串数组、字节数组等都是多路复用的,不重复创建,大大减少了无用对象的创建,从而实现“零GC”。支持更高性能的I/O编写log4j还提供了MemoryMappedFileAppender,I/O部分使用MemoryMappedFile实现,可以获得极高的I/O性能。但是在使用MemoryMappedFileAppender之前,请确保您对MemoryMappedFile有足够的了解,否则不要轻易使用它。更强大的参数格式化API模块,提供了比slf4j更丰富的参数格式化功能。使用{}占位符格式化参数在slf4j中,我们可以使用{}来实现“格式化”功能(参数会直接用toString替换占位符),像这样:logger.debug("Logginginuser{}withbirthday{}",user.getName(),user.getBirthdayCalendar());复制代码使用String.format格式化参数在log4j2中,除了支持{}参数占位符外,还支持String.format的形式:publicstaticLoggerlogger=LogManager.getFormatterLogger("Foo");logger.debug("Logginginuser%swithbirthday%s",user.getName(),user.getBirthdayCalendar());logger.debug("登录用户%1$swithbirthday%2$tm%2$te,%2$tY",user.getName(),用户.getBirthdayCalendar());logger.debug("Integer.MAX_VALUE=%,d",Integer.MAX_VALUE);logger.debug("Long.MAX_VALUE=%,d",Long.MAX_VALUE);复制代码**注意如果要使用String.format的形式,需要使用LogManager.getFormatterLogger而不是LogManager.getLogger**在log4j2的Logger接口中使用logger.printf格式化参数,也有printf方法,不用创建LogManager.getFormatterLogger,可以使用String.formatlogger.printf(Level.INFO,"Logginginuser%1$swithbirthday%2$tm%2$te,%2$tY",user.getName(),user的形式。GetBirthdayCalendar());logger.debug("Openingconnectionto{}...",someDataSource);复制代码“懒惰”日志记录(lazylogging)是一个小功能,但在一些业务流程中却非常有用。或者为了追查问题,需要将输入的参数完整打印出来。通常,输入参数用JSON/XML序列化,然后在调试级别打印:logger.debug("Inputparametermessage:{}",JSON.toJSONString(policyDTO));如果在copy代码的时候需要trace问题,系统的log级别会调整为debug/trace,这样就可以打印出来了。但是这里有一个问题。debug虽然不会输出info级别的内容,但是序列化代码JSON.toJSONString()肯定会被执行,严重影响正常流程下的执行效率。我们期望的结果是,在info层面,连序列化都不做。这里可以通过isDebugEnable判断当前配置下是否可以输出debug级别:if(logger.isDebugEnabled()){logger.debug("Inputmessage:{}",JSON.toJSONString(policyDTO));}复制像这样的代码虽然可以避免不必要的序列化,但是到处这样写还是有点难受,一行变成三行。log4j2的logger对象提供了一系列的lambda支持。通过这些接口,可以实现“惰性”日志记录:.paramSuppliers);voiderror(Stringmessage,Supplier>...paramSuppliers);//相当于下面先判断,然后打印logger.debug("Inputparametermessage:{}",()->JSON.toJSONString(policyDTO));if(logger.isDebugEnabled()){logger.debug("Inputmessage:{}",JSON.toJSONString(policyDTO));}复制Supplier+Lambda形式的代码相当于上面先判断isDebugEnable再打印的方法,三行代码变成一行。嗯,很好吃。简化配置Log4j2同时支持XML/JSON/YML/Properties四种配置文件,但最主流或者说最直观的方式还是XML。我们来看看logback和log4j2配置文件的对比。相同功能的配置下:logback.xml