快捷搜索:  汽车  科技

java打日志需要注意什么(用了这么多年的java日志框架)

java打日志需要注意什么(用了这么多年的java日志框架)import org.apache.log4j.Logger; public class Log4jTest { private final static Logger logger = Logger.getLogger("logTest"); public static void main(String[] args) { logger.info("log4j test"); } }二、jul<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency&

在项目开发过程中,有一个必不可少的环节就是记录日志,相信只要是个程序员都用过,可是咱们自问下,用了这么多年的日志框架,你确定自己真弄懂了日志框架的来龙去脉嘛?下面笔者就详细聊聊java中常用日志框架的关系及使用方法。

java打日志需要注意什么(用了这么多年的java日志框架)(1)

如上图,在开发过程中常用的日志框架大概包括:log4j、jul、jcl、slf4j几种,其中log4j和jul是两种具体的日志实现框架,而jcl和slf4j则不是一个具体的实现框架,而只是日志框架的搬运工,他们定义了日志的接口,底层具体使用的是log4j或jul,具体关系可以参考上图所示。朋友们是不是有个疑问,既然有了Log4j和jul这种日志实现框架,那为啥还要有jcl和slf4j两个框架呢?这里根据具体的项目来说明。

在实际的项目开发过程中,随着项目的变动,什么新需求,人员变动都是很正常的,假如有一个项目很早的时候架构师使用的是jul作为日志框架,当项目运行一段实践后,新来了一个项目经理,接到了一个新的需求,需要更换成log4j日志框架(原因有很多),请问这时候需要怎么办呢?如果要更换,那么修改的成本就比较高了,需要修改整个系统了,复杂度可想而知。可是如果使用的是jcl或者slf4j这种框架,那情况就完全不一样了,因为jcl和slf4j采用的是面向“接口编程”的设计方式,它不是一种具体的日志实现,可以灵活支持其他的日志实现框架,这样如果需要从原来的使用jul更换成log4j,那就轻松多了,只要修改下依赖就可以搞定了。

好了,废话少说,下面详细描述每种日志框架的具体应用及实现原理:

一、log4j

log4j是java日志框架的一种具体实现,可以说是目前java项目中使用最广泛的日志框架,使用步骤如下:

1.添加log4j依赖

<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>

2.使用demo

import org.apache.log4j.Logger; public class Log4jTest { private final static Logger logger = Logger.getLogger("logTest"); public static void main(String[] args) { logger.info("log4j test"); } }

二、jul

jul全程是java Util Log,它是jdk自带的日志实现,不需要引入其他依赖包,直接使用即可。

import java.util.logging.Logger; public class JulLogTest { private final static Logger logger = Logger.getLogger("JulLogTest"); public static void main(String[] args) { logger.info("jul test"); } }

三、jcl

jcl是java commons logging的简称,它不是具体的日志实现框架,而是一种日志框架的抽象,使用步骤如下:

1.添加commons logging依赖包

注意log4j的依赖包不是必须的,如果没有引入log4j依赖包,则使用的是jul日志实现:

<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <!--log4j日志配置--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>

2.使用demo

import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class JclLogTest { private final static Log log = LogFactory.getLog("jclLogTest"); public static void main(String[] args) { log.info("jcl test"); } }

3.原理分析

jcl是如何实现灵活使用不同的日志实现框架的呢?从上述实例中,咱们进入LogFactory的具体实现类LogFactoryImpl的getInstance方法,这个方法是获取具体Log对象的方法:

public Log getInstance(String name) throws LogConfigurationException { Log instance = (Log) instances.get(name); if (instance == null) { instance = newInstance(name); instances.put(name instance); } return instance; }

在newInstance方法中有一段代码:

instance = discoverLogImplementation(name);

这段代码调用discoverLogImplementation去发现日志的具体实现:

for(int i=0; i<classesToDiscover.length && result == null; i) { result = createLogFromClass(classesToDiscover[i] logCategory true); }

在discoverLogImplementation方法中,默认情况下,会进入如上代码逻辑,其中classesToDiscover数组列出了jcl默认支持的日志实现类,如下代码所示,好了,现在大家清楚了嘛?jcl是循环加载这个数组中的对象,加载到了就返回了,所以从代码中咱们可以看出,jcl优先的日志实现是有先后顺序的,优先使用的是log4j:

private static final String[] classesToDiscover = { "org.apache.commons.logging.impl.Log4JLogger" "org.apache.commons.logging.impl.Jdk14Logger" "org.apache.commons.logging.impl.Jdk13LumberjackLogger" "org.apache.commons.logging.impl.SimpleLog" };

四、slf4j

1.添加slf4j依赖包

<!-- slf4j配置 slf4j-api是接口包,必须引入 以下三个随便选择一个: slf4j绑定的依赖,slf4j-jcl绑定jcl,也就是绑定jcl作为具体的日志实现 slf4j-log4j12则是绑定log4j,使用log4j作为具体的日志实现 slf4j-jdk14绑定JDK,使用jdk默认的日志实现 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jcl</artifactId> <version>1.7.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>1.7.2</version> <scope>runtime</scope> </dependency>

2.使用demo

import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Slf4jLogTest { private final static Logger logger = LoggerFactory.getLogger("Slf4jLogTest"); public static void main(String[] args) { logger.info("slf4j test"); } }

3.原理分析

slf4j采用的是绑定机制来确定具体的日志实现框架,具体如何绑定呢?这里我们进入LoggerFactory.getLogger方法:

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

这里返回的Logger对象是从ILoggerFactory接口的具体实现类返回的,继续进入getILoggerFactory方法,在该方法中我们可以看到有如下代码:

return StaticLoggerBinder.getSingleton().getLoggerFactory();

好了,核心就是这个StaticLoggerBinder实现类,这个实现类在slf4j-log4j12、slf4j-jcl、slf4j-jdk14这三个不同的依赖jar包中都有自己的实现,从而通过不同的日志工厂类(ILoggerFactory)得到不同的Logger对象。

以上就是咱们项目过程中常用的日志框架关系整理,欢迎大家一起来交流学习。

猜您喜欢: