愉快地学Java语言:第十五章 断言与日志

导读

本文适合Java入门,不太适合Java中高级软件工程师。本文以《Java核心技术基础知识卷I》第10版为蓝本,采用不断提出问题,然后解答问题的方式来讲述。本篇文章只是这个系列中的一篇,如果你喜欢这种讲解方式,或者觉得从中能学到知识,可以关注我,以便查阅本系列其他文章。

让我们开始愉快地学习Java语言吧!

愉快地学Java语言:第十五章 断言与日志

1断言

为啥使用断言?

断言使程序具有自我保护能力!

我们在开发和测试阶段,会加入一些检测代码辅助调试,这些代码会随其他代码一起发布,这样势必对性能有影响。断言机制允许在测试期间向代码中插入一些检査语句。当代码发布时,这些插人的检测语句将会被自动地移走。这样正式发布时,程序不会因为有大量的检查语句而影响性能。

断言只用于开发和测阶段,确定程序内部的错误位置。

断言的两种形式

1)assert 条件;

2)assert 条件:表达式;

断言执行的时候,对条件进行检测,如果条件结构为false, 则抛出一个 AssertionError异常。

第二种形式与第一种的区别就是:表达式被传入AssertionError的构造器并转换成一个消息字符串。使用这个表达式的目的只有一个:产生一个消息字符串。所以一定不要使用这个表达式向客户端传递任何跟业务相关的信息。

启用与禁用断言

那么是谁控制断言的启用与禁用呢?

这是类加载器的职责。所以启用或禁用断言时不必重新编译程序。

当断言被禁用时,类加载器将跳过断言代码。

如何启用断言呢?

在默认情况下, 断言被禁用,那么我们要像下面这样设置才能启用断言。

1)对于由类加载器加载的类而言:

用 -enableassertions 或 -ea 选项启用。

例:java -enableassertions MyApp

也可以在某个类或整个包中使用断言:

java -ea:MyClass -ea iconi.inycompany.inylib... MyApp

2)不是由类加载器加载,而是直接由虚拟机加载的类:

使用 -enablesystemassertions/-esa 开关启用断言

如何禁用断言呢?

1)对于由类加载器加载的类而言:

使用-da禁用断言

2)不是由类加载器加载,而是直接由虚拟机加载的类:

使用-dsa禁用断言

2日志

Java API提供的日志记录器

为什么要记录日志呢?

当你开发程序时,会在有问题的代码中插入System.out.println方法,以便打印执行的结果,好助你找到发生错误的位置。但是在发布时,一定要删除这些“无用”的代码,这样做太麻烦了,因此我们找到了更好的办法,那就是记录日志。至此我们有了三大武器:异常、断言、日志,使程序具有自我保护能力,同时也方便我们调试代码。

Java API提供了相应类:java.util.logging.Logger。本文简单介绍下这个类的使用,因为在日常的开发中,我们使用最多的还是其他日志组件,譬如SLF4J,log4j。

获取日志记录器

private static final Logger logger= Logger.getLogger (“LoggerName”);

LoggerName:每个日志记录器都有一个名字

为什么要将logger声明为静态变量呢?

因为未被任何变量引用的日志记录器可能会被垃圾回收,所以用一个静态变量存储日志记录器的一个引用。

日志记录器的级别

日志记录器有七个级别,从高到低依次为:SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST。

设置日志记录器的级别有什么用呢?

可以有选择地输出不同等级的记录。默认情况下,只记录前三个级别,可以使用Level.ALL开启所有级别的记录,使用Level.OFF关闭日志。

修改日志配置

一般日志配置文件位于jre/lib/1ogging.properties,可以配置java.util.logging.config.file特性,指定其他的位置。

java - Djava.util.logging.config.file=configFile MainClass。

3SLF4J

3.1 SLF4J使用模式

SLF4J是简单日志系统的Facade(门面),它为程序员提供了便利的方法,允许程序员在编写代码时不必考虑使用何种具体的日志组件,而在部署程序时在考虑这些,下面是一般的使用模式。

愉快地学Java语言:第十五章 断言与日志

3.2 SLF4J概要

SLF4J只有一个强制依赖:slf4j-api,可以使用Maven管理依赖,例如使用1.7.25版本:

<dependency>

<groupid>org.slf4j/<groupid>

<artifactid>slf4j-api/<artifactid>

<version>1.7.25/<version>

从1.6.0版本开始,如果在类路径下没有找到绑定,那么SLF4J将默认为无操作的实现。

从1.7.0版本开始,Logger接口提供了接收可变参数的打印方法,而不是如以前的接口那样参数类型为Object[]。1.6.X版本中的由编译器生成的Logger接口,1.7.X版本是无法理解的。1.7.X版本与1.6.X版本不兼容。

从1.7.5开始,显著提高了记录器检索时间。鉴于改进的程度,强烈建议用户迁移到1.7.5或更高版本。

从1.7.9版本开始,通过设置slf4j.detectLoggerNameMismatch这一系统属性为true,SLF4J能自动地发现错误命名的Logger。

3.3 SLF4J绑定

SLF4J绑定是一种jar文件,它有多种类型。

我们运行上面的例子,运行结果如下:

愉快地学Java语言:第十五章 断言与日志

打印错误的原因是,在类路径下没有找到SLF4J绑定()。

如果你将slf4j-simple的依赖配置pom.xml中上述报错就会消失。slf4j-simple是SLF4J的一个简单实现。注意引入的版本要和slf4j-api匹配,例如slf4j-api我使用1.7.25版本,那么slf4j-simple我也是使用1.7.25版本。

<dependency>

<groupid>org.slf4j/<groupid>

<artifactid>slf4j-simple/<artifactid>

<version>1.7.25/<version>

运行结果为:

愉快地学Java语言:第十五章 断言与日志

除了slf4j-simple这个绑定以外,还有几种其他类型的绑定,每种绑定都对应着一种具体日志组件。

1)slf4j-log4j12

这个绑定对应着log4j这个日志组件。pom.xml配置如下:

<dependency>

<groupid>org.slf4j/<groupid>

<artifactid>slf4j-log4j12/<artifactid>

<version>1.7.21/<version>

<dependency>

<groupid>log4j/<groupid>

<artifactid>log4j/<artifactid>

<version>1.2.17/<version>

2)slf4j-jdk14

这个绑定对应java.util.logging,即JDK提供的日志组件

3)slf4j-nop

这个绑定对应NOP,即no operation,默认地不记录所有日志。既然不记录日志,那么我们引入它有什么用呢?

如果不引入这个jar,那么会像上面那样输出错误信息。

4)slf4j-jcl

这个绑定对应Apache Commons Logging,也被称为 Jakarta Commons Logging。

5)logback-classic

这个绑定对应的是logback,近年来,好多公司由log4j转向logback。Logback的ch.qos.logback.classic.Logger类直接实现了org.slf4j.Logger接口,因此,将SLF4J与logback结合使用会大量地减少内存和计算的开销。

现在,想要切换日志框架是一件非常简单的事情,只要改变Maven的依赖配置就行。

切记,不能同时使用两种日志框架。

借用官网的一张图,来说明它们的关系。

愉快地学Java语言:第十五章 断言与日志

3.4 SLF4J+log4j示例

下面以使用log4j为例,添加log4j后。运行后发现,报错。

愉快地学Java语言:第十五章 断言与日志

这是没有配置log4j的原因导致的。

那么我们创建资源文件夹src/main/resource,在此文件夹下添加配置文件log4j.properties,并按如下配置:

愉快地学Java语言:第十五章 断言与日志

使用下列语句加载配置文件:

URL configURL = App.class.getClassLoader().getResource("log4j.properties");

PropertyConfigurator.configure(configURL);

运行结果如下:

愉快地学Java语言:第十五章 断言与日志

我们配置将info信息输出到文件,可以看到确实有一个名为info的文件。

愉快地学Java语言:第十五章 断言与日志


分享到:


相關文章: