logger里的层级结构关系如下图:

我们可以看到,如果我们自己没有设置当前某个包范围内的logger优先级,那么它默认就是继承root logger的优先级。像上图中,root logger定义的优先级是WARN,那么,com这个范围内的logger默认的就是warn。所以这时如果我们去尝试输出低于WARN级别的日志,是不会看到有任何输出的。因为它们都被屏蔽了。
比如说,如果我们有一个如下的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{DEFAULT} [%t] %-5p %c{36} - %m%n"/>
</Console>
</appenders>
<loggers>
<root level="warn">
<appender-ref ref="Console" />
</root>
</loggers>
</configuration>
我们同时有如下的代码:
package com.wrox;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class App {
private static Logger logger = LogManager.getLogger();
public static void main( String[] args ) {
logger.warn("info log");
}
}
程序将输出如下的内容:
2018-02-15 15:42:36,126 [main] WARN com.wrox.App - warn log
但是,如果我们将logger.warn改成更低的像logger.info, logger.debug。那么将看不到任何输出。
看来这种logger继承关系也有一个好处,就是如果我们不想自定义自己的Logger优先级,只要有一个定义好的父logger就省事了。当然,在很多情况下因为我们需要不同优先级别的logger,我们需要做一些调整。有时候我们不希望继承它的父logger的配置。那该怎么办呢?我们可以通过配置logger的additivity属性来实现。它表示是否继承父logger的属性。默认值是true。所以,如果我们配置一个如下的logger信息的话:
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{DEFAULT} [%t] %-5p %c{36} - %m%n"/>
</Console>
</appenders>
<loggers>
<root level="warn">
<appender-ref ref="Console" />
</root>
<logger name="com.wrox" level="info" additivity="false">
<appender-ref ref="Console"/>
</logger>
</loggers>
</configuration>
我们在这里新建了一个logger,它不会继承root logger的属性,所以在这个包com.wrox以及它的子包里的所有logger都默认继承自它了。如果我们在代码里尝试如下的代码:

logger.info("info log");
我们可以看到如下的输出:
2018-02-15 15:47:15,805 [main] INFO com.wrox.App - info log
所以,在这里root logger的限制对它来说就不起作用了。
关于获取logger的地方,还有一个细节值得我们注意。就是在前面定义的配置文件里,我们一般是指定它所在的包及范围。当然,也可以设置一个指定的logger name。比如说我们将配置文件设置成如下的方式:
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{DEFAULT} [%t] %-5p %c{36} - %m%n"/>
</Console>
</appenders>
<loggers>
<root level="warn">
<appender-ref ref="Console" />
</root>
<logger name="com.wrox" level="info" additivity="false">
<appender-ref ref="Console"/>
</logger>
<logger name="sample" level="info">
<appender-ref ref="Console"/>
</logger>
</loggers>
</configuration>
在这里,我们定义了一个名字为"sample"的logger。那么,我们该如何引用这个logger呢?我们可以通过在代码里引用这个名字的logger。具体的引用代码如下:
private static Logger logger = LogManager.getLogger("sample");
当然,如果我们执行程序的话,会发现同样的日志给输出了两遍:
2018-02-15 15:50:49,302 [main] INFO sample - info log 2018-02-15 15:50:49,302 [main] INFO sample - info log
但是使用类的方式来实现厂模式还有更多的好处. 其一是: 我们可以管理从 nsisupports 接口派生而来的类厂本身的生存期. 当我们试图把多个类厂划分成一组, 然后确定是否能卸载这一组类厂的时候, 这一点非常重要. 另一个好处是: 类厂可以引入其他需要支持的接口. 在我们后面讨论 nsiclassinfo 接口的时候, 我们会看到某些类厂使用这个接口支持信息查询, 诸如这个对象是用什么语言写的, 对象支持的接口等等. 这种派生自 nsisupports 的 "future-proofing" 特性非常关键.xpidl 与类型库定义接口的简单而强劲的方法是使用接口定义语言 - 这实际上是在一个跨平台而语言无关开发环境下定义接口的需求. xpcom 使用的是源自于 corba omg 接口定义语言的变体, 称为 xpidl, 来定义接口, xpidl 可以定义接口的方法, 属性, 常量, 以及接口继承.采用 xpidl 定义接口还存在一些缺陷. 它不支持多继承, 同时 xpidl 定义的方法名不能相同。lpthreadattributes :null使用默认安全性,不可以被子线程继承,否则需要定义一个结构体将它的binherithandle成员初始化为true。一些面向对象的语言提供叫做"多重继承"的特点,当一个对象需要从多于一个的基类继承行为和属性的时候这是有价值的.多重继承在有些情况下是复杂的.例如,假设我们需要定义一个基类,animal,然后是animal的两个子类,landanimal 和 wateranimal.现在我们想要定义一个类来代表青蛙.青蛙是两栖动物,所以我们自然会想到定义frog类从landanimal和wateranimal类继承.这使得frog类能够同时从landanimal 和wateranimal类继承所需的行为和属性.。
在log4j2里,还有一个比较重要的特性,就是asyncLogger。因为它不是通过同步的方式将日志发送记录下来,而是采用异步的方式。这种方式带来的好处就是日志记录上的性能有极大的提升。在某些情况下,我们可以考虑采用它来配置日志。
采用AsyncLogger需要使用一个额外的依赖,就是库disruptor。它的依赖如下:
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.7</version>
</dependency>
有了这个之后,它的日志配置还是挺简单的,一个具体的示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="WARN">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{DEFAULT} [%t] %-5p %c{36} - %m%n"/>
</Console>
<RollingFile name="WroxFileAppender" fileName="../logs/application.log"
filePattern="../logs/application-%d{MM-dd-yyyy}-%i.log">
<PatternLayout>
<pattern>%d{DEFAULT} [%t] %X{id} %X{username} %-5p %c{36}: %msg%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<DefaultRolloverStrategy min="1" max="4" />
</RollingFile>
</appenders>
<loggers>
<root level="warn">
<appender-ref ref="Console" />
</root>
<AsyncLogger name="com.wrox" level="info" includeLocation="true" additivity="false">
<appender-ref ref="WroxFileAppender"/>
<appender-ref ref="Console"/>
</AsyncLogger>
</loggers>
</configuration>
在这个示例里,我们定义了两个appender,一个是console,一个是RollingFile。我们定义的AsyncLogger只需要在loggers元素里定义这么一个项,然后将appender引用进来就可以了。
在应用程序里,记录日志是一个看起来很细小但是却很重要的步骤。如何记录日志,选择合适的日志框架也是一个需要仔细思考的问题。日志的记录方式,保存和处理方式,记录的格式等等都牵涉到很多的细节。并不像我们想象的那么简单。
compile 'org.apache.logging.log4j:log4j-slf4j-impl:2.5'。 compile 'org.apache.logging.log4j:log4j-core:2.5'。 compile 'org.apache.logging.log4j:log4j-api:2.5'。
https://stackify.com/log4j2-java/
https://stackify.com/java-logging-best-practices/
professional java for web applications
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-116994-3.html
当老师的说的都是美好的
休渔期结束