<div class="htmledit_views">html
<p><strong>参考:<a href="http://singleant.iteye.com/blog/934593" target="_blank">http://singleant.iteye.com/blog/934593</a> <a href="http://liuzidong.iteye.com/blog/776072" target="_blank">http://liuzidong.iteye.com/blog/776072</a></strong></p> <p>介绍<span style="font-family:Tahoma, Helvetica, Arial, STHeiti;font-size:14px;color:#454545;line-height:21px;">:</span></p> <p><span style="font-family:Tahoma, Helvetica, Arial, STHeiti;font-size:14px;color:#454545;line-height:21px;"> 简单日记门面(simple logging Facade for java)SLF4J是为各类loging APIs提供一个简单统一的接口,从而使得最终用户可以在部署的时候配置本身但愿的loging APIs实现。 Logging API实现既能够选择直接实现SLF4J接的loging APIs如: NLOG4J、SimpleLogger。也能够经过SLF4J提供的API实现来开发相应的适配器如Log4jLoggerAdapter、JDK14LoggerAdapter。在SLF4J发行版本中包含了几个jar包,如slf4j-nop.jar, slf4j-simple.jar, slf4j-log4j12.jar, slf4j-log4j13.jar, slf4j-jdk14.jar and slf4j-jcl.jar经过这些jar文件可使编译期与具体的实现脱离。或者说能够灵活的切换,咱们在开发过程当中可能使用各类log,每一个Log有不一样的风格、布局,若是想灵活的切换那么slf4j是比较好的选择。<span style="font-family:Arial;color:#333333;line-height:26px;">SLF4J不是具体的日志解决方案,它只服务于各类各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,容许最终用户在部署其应用时使用其所但愿的日志系统。</span></span><br></p> <p><span style="font-family:Tahoma, Helvetica, Arial, STHeiti;font-size:14px;color:#454545;line-height:21px;"><br></span></p> <p><strong>1、 概念</strong></p> <p><strong><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">Log4j</span><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"> </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">Apache的一个开放源代码项目,经过使用Log4j,咱们能够控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务 器、NT的事件记录器、UNIX Syslog守护进程等;用户也能够控制每一条日志的输出格式;经过定义每一条日志信息的级别,用户可以更加细致地控制日志的生成过程。这些能够经过一个 配置文件来灵活地进行配置,而不须要修改程序代码。是 经典的一种日志解决方案。内部把日志系统抽象封装成Logger 、appender 、pattern 等实现。咱们能够经过配置文件轻松的实现日志系统的管理和多样化配置。</span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">LOGBack </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">Logback是由log4j创始人设计的又一个开源日记组件。logback当前分红三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个 改良版本。此外logback-classic完整实现SLF4J API使你能够很方便地更换成其它日记系统如log4j或JDK14 Logging。logback-access访问模块与Servlet容器集成提供经过Http来访问日记的功能。</span></strong><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><strong>LOGBack 做为一个通用可靠、快速灵活的日志框架,将做为Log4j 的替代和SLF4J 组成新的日志系统的完整实现。官网上称具备极佳的性能,在关键路径上执行速度是log4j 的10 倍,且内存消耗更少。具体优点见:</strong></span><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><strong>http://logback.qos.ch/reasonsToSwitch.html</strong></span><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><strong><br></strong></span><strong><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">Log4J vs. LOGBack</span><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"> </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">LOGBack做为一个通用可靠、快速灵活的日志框架,将做为Log4j的替代和SLF4J组成新的日志系统的完整实现。LOGBack声称具备极佳的性能,“ 某些关键操做,好比断定是否记录一条日志语句的操做,其性能获得了显著的提升。这个操做在LogBack中须要3纳秒,而在Log4J中则须要30纳秒。 LogBack建立记录器(logger)的速度也更快:13微秒,而在Log4J中须要23微秒。更重要的是,它获取已存在的记录器只需94纳秒,而 Log4J须要2234纳秒,时间减小到了1/23。跟JUL相比的性能提升也是显著的”。 </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">另外,LOGBack的全部文档是全面免费提供的,不象Log4J那样只提供部分免费文档而须要用户去购买付费文档。 </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">SLF4J </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">简单日记门面(Facade)SLF4J是为各类loging APIs提供一个简单统一的接口,从而使得最终用户可以在部署的时候配置本身但愿的loging APIs实现。 Logging API实现既能够选择直接实现SLF4J接的loging APIs如: NLOG4J、SimpleLogger。也能够经过SLF4J提供的API实现来开发相应的适配器如Log4jLoggerAdapter、JDK14LoggerAdapter。 </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">Apache Common-Logging </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">目前普遍使用的Java日志门面库。经过动态查找的机制,在程序运行时自动找出真正使用的日志库。但因为它使用了ClassLoader寻找和载入底层的日志库, 致使了象OSGI这样的框架没法正常工做,因为其不一样的插件使用本身的ClassLoader。 OSGI的这种机制保证了插件互相独立,然而确使Apache Common-Logging没法工做。 apache最先提供的日志的门面接口。避免和具体的日志方案直接耦合。相似于JDBC 的api 接口,具体的的JDBC driver 实现由各数据库提供商实现。经过统一接口解耦,不过其内部也实现了一些简单日志方案。</span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">SLF4J vs. Apache Common-Logging</span><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"> </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">SLF4J库相似于Apache Common-Logging。可是,他在编译时静态绑定真正的Log库。使用SLF4J时,若是你须要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合。 如此即可以在OSGI中使用了。 </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">另外,SLF4J 支持参数化的log字符串,避免了以前为了减小字符串拼接的性能损耗而不得不写的if(logger.isDebugEnable()),如今你能够直接写:logger.debug(“current user is: {}”, user)。拼装消息被推迟到了它可以肯定是否是要显示这条消息的时候,可是获取参数的代价并无幸免。同时,日志中的参数若超过三个,则须要将参数以数组的形式传入,如: </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">Object[] params = {value1, value2, value3}; </span><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">logger.debug(“first value: {}, second value: {} and third value: {}.”, params); </span></strong></p> <p><strong><br style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;"><span style="font-family:Helvetica, Tahoma, Arial, sans-serif;font-size:14px;line-height:25.1875px;">如今,Hibernate、Jetty、Spring-OSGi、Wicket和MINA等项目都已经迁移到了SLF4J,因而可知SLF4J的影响力不可忽视。 </span></strong></p> <p><br></p> <p><strong> Slf4j</strong>全称为Simple Logging Facade for JAVA:java简单日志门面。 是对不一样日志框架提供的一个门面封装。能够在部署的时候不修改任何配置便可接入一种日志实现方案。和commons-loging 应该有同样的初衷。我的感受设从计上更好一些,没有commons 那么多潜规则。同时有两个额外特色:</p> <p>1. 能支持多个参数,并经过{} 占位符进行替换,避免老写logger.isXXXEnabled 这种无奈的判断,带来性能提高见:http://www.slf4j.org/faq.html#logging_performance 。</p> <p>2.OSGI 机制更好兼容支持,官网上的一个图:</p> <p><img src="https://img-blog.csdn.net/20130718110353109?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29ucXVlcjA3MTU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" height="800" width="600"><br></p> <p>从上图能够发现,选择仍是不少的。</p> <p><strong>2、 常见日志方案和注意事项</strong></p> <p><strong>1.Commons-logging+log4j </strong>: 经典的一个日志实现方案。出如今各类框架里。如spring 、webx 、ibatis 等等。直接使用log4j 便可知足咱们的日志方案。可是通常为了不直接依赖具体的日志实现,通常都是结合commons-logging 来实现。常见代码以下:</p> <p>import org.apache.commons.logging.Log;</p> <p>import org.apache.commons.logging.LogFactory;</p> <p>private static Log logger = LogFactory.getLog(CommonsLoggingTest.class);</p> <p>代码上,没有依赖任何的log4j 内部的类。那么log4j 是如何被装载的?</p> <p>Log 是一个接口声明。LogFactory 的内部会去装载具体的日志系统,并得到实现该Log 接口的实现类。而内部有一个Log4JLogger 实现类对Log 接口同时内部提供了对log4j logger 的代理。LogFactory 内部装载日志系统流程:</p> <p>1. 首先,寻找org.apache.commons.logging.LogFactory 属性配置</p> <p><span style="color:#FF0000;">2. </span><span style="color:#FF0000;">不然,利用JDK1.3 开始提供的service 发现机制,会扫描classpah 下的META-INF/services/org.apache.commons.logging.LogFactory 文件,若找到则装载里面的配置,使用里面的配置。</span></p> <p>3. 不然,从Classpath 里寻找commons-logging.properties ,找到则根据里面的配置加载。</p> <p>4. 不然,使用默认的配置:若是能找到Log4j 则默认使用log4j 实现,若是没有则使用JDK14Logger 实现,再没有则使用commons-logging 内部提供的SimpleLog 实现。</p> <p>从上述加载流程来看,若是没有作任何配置,只要引入了log4j 并在classpath 配置了log4j.xml ,则commons-logging 就会使log4j 使用正常,而代码里不须要依赖任何log4j 的代码。</p> <p><br></p> <p><strong>2.Commons-logging+log4j+slf4j</strong></p> <p>若是在原有commons-logging 系统里,若是要迁移到slf4j, 使用slf4j 替换commons-logging ,也是能够作到的。原理使用到了上述commons-logging 加载的第二点。须要引入Org.slf4j.jcl-over-slf4j-1.5.6.jar 。这个jar 包提供了一个桥接,让底层实现是基于slf4j 。原理是在该jar 包里存放了配置META-INF/services/org.apache.commons.logging.LogFactory =org.apache.commons.logging.impl.SLF4JLogFactory,而commons-logging 在初始化的时候会找到这个serviceId ,并把它做为LogFactory 。</p> <p>完成桥接后,那么那么简单日志门面SLF4J 内部又是如何来装载合适的log 呢?</p> <p>原理是SLF4J 会在编译时会绑定<span style="color:#FF0000;">import org.slf4j.impl.StaticLoggerBinder;</span> 该类里面实现对具体日志方案的绑定接入。任何一种基于slf4j 的实现都要有一个这个类。如:</p> <p>org.slf4j.slf4j-log4j12-1.5.6: 提供对 log4j 的一种适配实现。</p> <p>Org.slf4j.slf4j-simple-1.5.6: 是一种 simple 实现,会将 log 直接打到控制台。</p> <p>……</p> <p><span style="color:#FF0000;">那么这个地方就要注意了:若是有任意两个实现slf4j 的包同时出现,那就有可能酿就悲剧,你可能会发现日志不见了、或都打到控制台了。缘由是这两个jar 包里都有各自的org.slf4j.impl.StaticLoggerBinder ,编译时候绑定的是哪一个是不肯定的。这个地方要特别注意!!出现过几回由于这个致使日志错乱的问题。</span></p> <p> </p> <p> </p> <p><strong><span style="font-size:14px;color:#3366ff;">3.使用SLf4j 很简单:</span></strong></p> <p><span style="font-size:14px;color:#3366ff;">import org.slf4j.Logger;<br> import org.slf4j.LoggerFactory;<br> public class TestSlf4j {<br><span style="white-space:pre;"></span>private static final Logger logger = LoggerFactory.getLogger(TestSlf4j.class);<br><span style="white-space:pre;"></span>public static void main(String[] args) {<br><span style="white-space:pre;"></span>logger.info(logger.getName());<br><span style="white-space:pre;"></span>}<br> }</span></p> <p>代码里也看不到任何具体日志实现方案的痕迹。</p> <div><br></div> </div>java