log4j2 slf4j,slf4j+logback
目录
slf4j1简单的使用案例注射毒品使用原理数字一(一)获取ILoggerFactory的过程注射毒品根据ILoggerFactory获取记录器的过程slf4j与java开发工具包日志记录集成数字一(一)需要的冲突包注射毒品使用案例3 使用案例原理分析数字一(一)获取ILoggerFactory的过程注射毒品根据ILoggerFactory获取记录器的过程slf4j与log4j1集成数字一(一)需要的冲突包注射毒品使用案例3 使用案例原理分析数字一(一)获取对应的ILoggerFactory2根据ILoggerFactory获取记录器的过程slf4j与log4j2集成数字一(一)需要的冲突包注射毒品使用案例3 使用案例原理分析数字一(一)获取对应的ILoggerFactory2根据ILoggerFactory获取记录器的过程slf4j与回溯集成数字一(一)需要的冲突包注射毒品使用案例3 使用案例原理分析数字一(一)获取对应的ILoggerFactory2根据ILoggerFactory获取记录器的过程结尾系列文章已完成,目录如下:
jdk-logginglog4jlogback日志系统实现机制原理介绍
公共日志记录与JDK-日志记录、日志4j1、日志4j2、日志返回的集成原理
slf4j、jcl、jul、log4j1、log4j2、logback大总结
slf4j
先从一个简单的使用案例来说明
1 简单的使用案例
私有静态日志记录器记录器=记录器工厂。获取日志程序(日志4 jsl F4 jtest。类);public static void main(String[]args){ if(logger。isdebugenabled()){ logger。调试( slf4j-log4j调试消息);} if(logger。isinfoenabled()){ logger。debug( slf4j-log4j info message );} if(logger。istrace enabled()){ logger。调试( slf4j-log4j跟踪消息);}}上述记录器接口伐木工厂类都是slf4j自己定义的。
2 使用原理
伐木工厂。获取日志程序(日志4 jsl F4 jtest。类)的源码如下:
公共静态记录器get Logger(字符串名称){ ILoggerFactory ILoggerFactory=getloggerfactory();返回iloggerfactory。获取记录器(名称);}上述获取原木的过程大致分成注射毒品个阶段
获取ILoggerFactory的过程(从字面上理解就是生产记录器的工厂)根据ILoggerFactory获取记录器的过程下面来详细说明:
1 获取ILoggerFactory的过程
又可以分成3个过程:
所以slf4j与其他实际的日志框架的集成冲突包中,都会含有这样的一个org/slf4j/impl/staticloggerbinder。班级类文件,并且提供一个ILoggerFactory的实现
1.1 从类路径中寻找org/slf4j/impl/staticloggerbinder。班级类类别载入器。获取系统资源( org/slf4j/impl/staticloggerbinder。类’)如果找到多个,则输出类别路径包含多个SLF4J绑定,表示有多个日志实现与slf4j进行了绑定
下面看下当出现多个静态记录器绑定器的时候的输出日志(简化了一些内容):
SLF4J:类路径包含多个SLF4J绑定100 . SLF 4j :在[slf4j-log4j12-1.7.12.jar中发现绑定!/org/slf4j/impl/staticloggerbinder。class]slf4j :在[日志备份-经典-1.1.3.jar中找到绑定!/org/slf4j/impl/staticloggerbinder。班级
]SLF4J: Found binding in [slf4j-jdk14-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]SLF4J: See http://www.slf4j.org/codes.htmlmultiple_bindings for an explanation.SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]1.2 "随机选取"一个StaticLoggerBinder.class来创建一个单例
StaticLoggerBinder.getSingleton()
这里的"随机选取"可以见官方文档说明:
SLF4J API is designed to bind with one and only one underlying logging framework at a time. If more than one binding is present on the class path, SLF4J will emit a warning, listing the location of those bindings
The warning emitted by SLF4J is just that, a warning. Even when multiple bindings are present,SLF4J will pick one logging framework/implementation and bind with it. The way SLF4J picks a binding is determined by the JVM and for all practical purposes should be considered random
1.3 根据上述创建的StaticLoggerBinder单例,返回一个ILoggerFactory实例
StaticLoggerBinder.getSingleton().getLoggerFactory()
2 根据ILoggerFactory获取Logger的过程
这就要看具体的ILoggerFactory类型了,下面的集成来详细说明
slf4j与jdk-logging集成
1 需要的jar包
slf4j-api
slf4j-jdk14
对应的maven依赖为:
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.12</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-jdk14</artifactId><version>1.7.12</version></dependency>
2 使用案例
private static final Logger logger=LoggerFactory.getLogger(JulSlf4jTest.class);public static void main(String[] args){if(logger.isDebugEnabled()){logger.debug("jul debug message");}if(logger.isInfoEnabled()){logger.info("jul info message");}if(logger.isWarnEnabled()){logger.warn("jul warn message");}}
上述的Logger、LoggerFactory都是slf4j自己的API中的内容,没有jdk自带的logging的踪影,然后打出来的日志却是通过jdk自带的logging来输出的,如下:
四月 28, 2015 7:33:20 下午 com.demo.log4j.JulSlf4jTest main信息: jul info message四月 28, 2015 7:33:20 下午 com.demo.log4j.JulSlf4jTest main警告: jul warn message
3 使用案例原理分析
先看下slf4j-jdk14 jar包中的内容:
从中可以看到:
的确是有org/slf4j/impl/StaticLoggerBinder.class类该StaticLoggerBinder返回的ILoggerFactory类型将会是JDK14LoggerFactoryJDK14LoggerAdapter就是实现了slf4j定义的Logger接口下面梳理下整个流程:
1 获取ILoggerFactory的过程
由于类路径下有org/slf4j/impl/StaticLoggerBinder.class,所以会选择slf4j-jdk14中的StaticLoggerBinder来创建单例对象并返回ILoggerFactory,来看下StaticLoggerBinder中的ILoggerFactory是什么类型:
private StaticLoggerBinder() { loggerFactory = new org.slf4j.impl.JDK14LoggerFactory();}
所以返回了JDK14LoggerFactory的实例
2 根据ILoggerFactory获取Logger的过程
来看下JDK14LoggerFactory是如何返回一个slf4j定义的Logger接口的实例的,源码如下:
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger(name);Logger newInstance = new JDK14LoggerAdapter(julLogger);
可以看到,就是使用jdk自带的logging的原生方式来先创建一个jdk自己的java.util.logging.Logger实例,参见jdk-logging的原生写法
然后利用JDK14LoggerAdapter将上述的java.util.logging.Logger包装成slf4j定义的Logger实例
所以我们使用slf4j来进行编程,最终会委托给jdk自带的java.util.logging.Logger去执行。
slf4j与log4j1集成
1 需要的jar包
slf4j-api
slf4j-log4j12
log4j
maven依赖分别为:
<!-- slf4j --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.12</version></dependency><!-- slf4j-log4j --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.12</version></dependency><!-- log4j --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>
2 使用案例
第一步:编写log4j.properties配置文件,放到类路径下
log4j.rootLogger = debug, consolelog4j.appender.console = org.apache.log4j.ConsoleAppenderlog4j.appender.console.layout = org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} %m%n
配置文件的详细内容不是本博客关注的重点,不再说明,自行搜索
第二步:代码中如下使用
private static Logger logger=LoggerFactory.getLogger(Log4jSlf4JTest.class);public static void main(String[] args){if(logger.isDebugEnabled()){logger.debug("slf4j-log4j debug message");}if(logger.isInfoEnabled()){logger.info("slf4j-log4j info message");}if(logger.isTraceEnabled()){logger.trace("slf4j-log4j trace message");}}
补充说明:
1 配置文件同样可以随意放置,如log4j1原生方式加载配置文件的方式log4j1原生开发
2 注意两者方式的不同:
slf4j: Logger logger=LoggerFactory.getLogger(Log4jSlf4JTest.class);log4j: Logger logger=Logger.getLogger(Log4jTest.class);
slf4j的Logger是slf4j定义的接口,而log4j的Logger是类。LoggerFactory是slf4j自己的类
3 使用案例原理分析
先来看下slf4j-log4j12包中的内容:
的确是有org/slf4j/impl/StaticLoggerBinder.class类该StaticLoggerBinder返回的ILoggerFactory类型将会是Log4jLoggerFactoryLog4jLoggerAdapter就是实现了slf4j定义的Logger接口来看下具体过程:
1 获取对应的ILoggerFactory
从上面的slf4j的原理中我们知道:ILoggerFactory是由StaticLoggerBinder来创建出来的,所以可以简单分成2个过程:
1.1 第一个过程:slf4j寻找绑定类StaticLoggerBinder
使用ClassLoader来加载 "org/slf4j/impl/StaticLoggerBinder.class"这样的类的url,然后就找到了slf4j-log4j12包中的StaticLoggerBinder
1.2 第二个过程:创建出StaticLoggerBinder实例,并创建出ILoggerFactory
源码如下:
StaticLoggerBinder.getSingleton().getLoggerFactory()
以slf4j-log4j12中的StaticLoggerBinder为例,创建出的ILoggerFactory为Log4jLoggerFactory
2 根据ILoggerFactory获取Logger的过程
来看下Log4jLoggerFactory是如何返回一个slf4j定义的Logger接口的实例的,源码如下:
org.apache.log4j.Logger log4jLogger;if (name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME)) log4jLogger = LogManager.getRootLogger();else log4jLogger = LogManager.getLogger(name);Logger newInstance = new Log4jLoggerAdapter(log4jLogger);
2.1 我们可以看到是通过log4j1的原生方式,即使用log4j1的LogManager来获取,引发log4j1的加载配置文件,然后初始化,最后返回一个org.apache.log4j.Logger log4jLogger,参见log4j1原生的写法
2.2 将上述的org.apache.log4j.Logger log4jLogger封装成Log4jLoggerAdapter,而Log4jLoggerAdapter是实现了slf4j的接口,所以我们使用的slf4j的Logger接口实例(这里即Log4jLoggerAdapter)都会委托给内部的org.apache.log4j.Logger实例
slf4j与log4j2集成
1 需要的jar包
slf4j-api
log4j-api
log4j-core
log4j-slf4j-impl (用于log4j2与slf4j集成)
对应的maven依赖分别是:
<!-- slf4j --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.12</version></dependency><!-- log4j2 --><dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.2</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.2</version></dependency><!-- log4j-slf4j-impl --><dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.2</version></dependency>
2 使用案例
第一步:编写log4j2的配置文件log4j2.xml,简单如下:、
<?xml version="1.0" encoding="UTF-8"?><Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="Console"/> </Root> </Loggers></Configuration>
第二步:使用方式
private static Logger logger=LoggerFactory.getLogger(Log4j2Slf4jTest.class);public static void main(String[] args){if(logger.isTraceEnabled()){logger.trace("slf4j-log4j2 trace message");}if(logger.isDebugEnabled()){logger.debug("slf4j-log4j2 debug message");}if(logger.isInfoEnabled()){logger.info("slf4j-log4j2 info message");}}
3 使用案例原理分析
先来看下log4j-slf4j-impl包中的内容:
的确是有org/slf4j/impl/StaticLoggerBinder.class类该StaticLoggerBinder返回的ILoggerFactory类型将会是Log4jLoggerFactory(这里的Log4jLoggerFactory与上述log4j1集成时的Log4jLoggerFactory是不一样的)Log4jLogger就是实现了slf4j定义的Logger接口来看下具体过程:
1 获取对应的ILoggerFactory
1.1 第一个过程:slf4j寻找绑定类StaticLoggerBinder
使用ClassLoader来加载 "org/slf4j/impl/StaticLoggerBinder.class"这样的类的url,然后就找到了log4j-slf4j-impl包中的StaticLoggerBinder
1.2 第二个过程:创建出StaticLoggerBinder实例,并创建出ILoggerFactory
log4j-slf4j-impl包中的StaticLoggerBinder返回的ILoggerFactory是Log4jLoggerFactory
2 根据ILoggerFactory获取Logger的过程
来看下Log4jLoggerFactory是如何返回一个slf4j定义的Logger接口的实例的,源码如下:
@Overrideprotected Logger newLogger(final String name, final LoggerContext context) { final String key = Logger.ROOT_LOGGER_NAME.equals(name) ? LogManager.ROOT_LOGGER_NAME : name; return new Log4jLogger(context.getLogger(key), name);}@Overrideprotected LoggerContext getContext() { final Class<?> anchor = ReflectionUtil.getCallerClass(FQCN, PACKAGE); return anchor == null ? LogManager.getContext() : getContext(ReflectionUtil.getCallerClass(anchor));}
上述获取LoggerContext的过程也是log4j2的原生方式:
LogManager.getContext()
该操作会去加载log4j2的配置文件,引发log4j2的初始化
2.1 我们可以看到是通过log4j2的原生方式,即使用log4j2的LoggerContext来获取,返回一个org.apache.logging.log4j.core.Logger即log4j2定义的Logger接口实例,参见log4j2原生的写法
2.2 将上述的org.apache.logging.log4j.core.Logger封装成Log4jLogger,而Log4jLogger是实现了slf4j的Logger接口的,所以我们使用的slf4j的Logger接口实例(这里即Log4jLogger)都会委托给内部的log4j2定义的Logger实例。
slf4j与logback集成
1 需要的jar包
slf4j-api
logback-core
logback-classic(已含有对slf4j的集成包)
对应的maven依赖为:
<!-- slf4j-api --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.12</version></dependency><!-- logback --><dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.3</version> </dependency>
2 使用案例
第一步:编写logback的配置文件logback.xml,简单如下:
<?xml version="1.0" encoding="UTF-8"?><configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
第二步:使用方式
private static final Logger logger=LoggerFactory.getLogger(LogbackTest.class);public static void main(String[] args){if(logger.isDebugEnabled()){logger.debug("slf4j-logback debug message");}if(logger.isInfoEnabled()){logger.info("slf4j-logback info message");}if(logger.isTraceEnabled()){logger.trace("slf4j-logback trace message");}}
3 使用案例原理分析
先来看下logback-classic包中与slf4j集成的内容:
的确是有org/slf4j/impl/StaticLoggerBinder.class类该StaticLoggerBinder返回的ILoggerFactory类型将会是LoggerContext(logback的对象)logback自己定义的ch.qos.logback.classic.Logger类就是实现了slf4j定义的Logger接口
1 获取对应的ILoggerFactory
1.1 第一个过程:slf4j寻找绑定类StaticLoggerBinder
使用ClassLoader来加载 "org/slf4j/impl/StaticLoggerBinder.class"这样的类的url,然后就找到了logback-classic包中的StaticLoggerBinder
1.2 第二个过程:创建出StaticLoggerBinder实例,并创建出ILoggerFactory
logback-classic包中的StaticLoggerBinder返回的ILoggerFactory是LoggerContext(logback的对象)
创建出单例后,同时会引发logback的初始化,这时候logback就要去寻找一系列的配置文件,尝试加载并解析。
2 根据ILoggerFactory获取Logger的过程
来看下LoggerContext(logback的对象)是如何返回一个slf4j定义的Logger接口的实例的:
该LoggerContext(logback的对象)返回的ch.qos.logback.classic.Logger(logback的原生Logger对象)就是slf4j的Logger实现类。
结尾
本篇文章讲解了slf4j与jdk-logging、log4j1、log4j2、logback的集成原理,下一篇也是最后一篇来总结下
各种jar包的总结commons-logging、slf4j与其他日志框架的集成总结实现已有的日志框架无缝切换到别的日志框架(如已使用log4j进行日志记录的代码最终转到logback来输出)jar包冲突说明以上就是slf4j与jul、log4j1、log4j2、logback的集成原理的详细内容,更多关于slf4j与jul log4j1 log4j2 logback集成原理的资料请关注盛行IT其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。