zoukankan      html  css  js  c++  java
  • Java 日志组件(二)

    3、log4j2

      log4j2与log4j发生了很大变化,不兼容。log4j仅仅作为一个实际的日志框架,slf4j、commons-logging作为门面统一各种日志框架的混乱格局,现在log4j2也想跳出来当门面,也想统一大家。日志越来越乱了

    • log4j-api:作为日志接口层,用于统一底层日志系统。
    • log4j-core:作为上述日志接口的实现,是一个实际的日志框架。

      3.1、maven依赖

     1 <dependency>
     2     <groupId>org.apache.logging.log4j</groupId>
     3     <artifactId>log4j-api</artifactId>
     4     <version>2.2</version>
     5 </dependency>
     6 <dependency>
     7     <groupId>org.apache.logging.log4j</groupId>
     8     <artifactId>log4j-core</artifactId>
     9     <version>2.2</version>
    10 </dependency>

      3.2、使用方式

      • 编写log4j2.xml配置文件(目前log4j2只支持xml、json、yuml,不再支持properties)
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <Configuration status="WARN">
     3   <Appenders>
     4     <Console name="Console" target="SYSTEM_OUT">
     5       <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
     6     </Console>
     7   </Appenders>
     8   <Loggers>
     9     <Root level="debug">
    10       <AppenderRef ref="Console"/>
    11     </Root>
    12   </Loggers>
    13 </Configuration>
      • 使用
     1 private static final Logger logger=LogManager.getLogger(Log4j2Test.class);
     2 
     3 public static void main(String[] args){
     4     if(logger.isTraceEnabled()){
     5         logger.debug("log4j trace message");
     6     }
     7     if(logger.isDebugEnabled()){
     8         logger.debug("log4j debug message");
     9     }
    10     if(logger.isInfoEnabled()){
    11         logger.debug("log4j info message");
    12     }
    13 }

        和log4j不同的是此时的Logger是log4j-api中定义的接口,而log4j中的Logger是类

      3.3、使用过程简单分析

      • 获取底层使用的LoggerContextFactory

            同样LogManager的类加载会去寻找log4j-api定义的LoggerContextFactory接口的底层实现,获取方式有三种

        • 尝试从jar中寻找log4j2.component.properties文件,如果配置了log4j2.loggerContextFactory则使用该LoggerContextFactory。
        • 如果没找到,尝试从jar包中寻找META-INF/log4j-provider.properties文件,如log4j-core-2.2中就有该文件。
        • 如果找到多个,取优先级最高的(该文件中指定了LoggerContextFactory,同时指定了优先级FactoryPriority),如log4j-core-2.2中log4j-provider.properties的文件内容如下 
    1 LoggerContextFactory = org.apache.logging.log4j.core.impl.Log4jContextFactory
    2 Log4jAPIVersion = 2.1.0
    3 FactoryPriority= 10
        • 上述方式还没找到,就使用默认的SimpleLoggerContextFactory
      • 使用LoggerContextFactory获取LoggerContext
      • 根据LoggerContext获取Logger
        • 会首先判断LoggerContext是否被初始化过了,没有则进行初始化
        • 获取ConfigurationFactory,从配置中获取和插件中获取(log4j-core核心包中有三个YamlConfigurationFactory、JsonConfigurationFactory、XmlConfigurationFactory)
        • 以上文的案例中,会使用XmlConfigurationFactory来加载log4j2.xml配置文件
        • LoggerContext初始化后,就可以获取或者创建Logger了

      3.4、主要对象总结

      • LogManager: 它的类加载会去寻找LoggerContextFactory接口的底层实现,会从jar包中的配置文件中寻找,如上面所述

      • LoggerContextFactory : 用于创建LoggerContext,不同的日志实现系统会有不同的实现,如log4j-core中的实现为Log4jContextFactory

      • PropertyConfigurator: 用于解析log4j.properties文件

      • LoggerContext : 它包含了配置信息,并能创建log4j-api定义的Logger接口实例,并缓存这些实例

      • ConfigurationFactory:上述LoggerContext解析配置文件,需要用到ConfigurationFactory,目前有三个YamlConfigurationFactory、JsonConfigurationFactory、XmlConfigurationFactory,分别解析yuml json xml形式的配置文件

    4、logback

      • logback-core
      • logback-classic
      • slf4j-api

      4.1、对应maven的依赖

     1 <dependency> 
     2     <groupId>ch.qos.logback</groupId> 
     3     <artifactId>logback-core</artifactId> 
     4     <version>1.1.3</version> 
     5 </dependency> 
     6 <dependency> 
     7     <groupId>ch.qos.logback</groupId> 
     8     <artifactId>logback-classic</artifactId> 
     9     <version>1.1.3</version> 
    10 </dependency>
    11 <dependency>
    12     <groupId>org.slf4j</groupId>
    13     <artifactId>slf4j-api</artifactId>
    14     <version>1.7.12</version>
    15 </dependency>

      4.2、使用

     1 private static final Logger logger=LoggerFactory.getLogger(LogbackTest.class);
     2 
     3 public static void main(String[] args){
     4     if(logger.isDebugEnabled()){
     5         logger.debug("slf4j-logback debug message");
     6     }
     7     if(logger.isInfoEnabled()){
     8         logger.debug("slf4j-logback info message");
     9     }
    10     if(logger.isTraceEnabled()){
    11         logger.debug("slf4j-logback trace message");
    12     }
    13     
    14     LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
    15     StatusPrinter.print(lc);
    16 }
      • 官方使用方式,其实就和slf4j集成了起来

        上述的Logger、LoggerFactory都是slf4j自己的接口与类

      • 没有配置文件的情况下,使用的是默认配置。搜寻配置文件的过程如下:

    1 Logback tries to find a file called logback.groovy in the classpath.
    2 If no such file is found, logback tries to find a file called logback-test.xml in the classpath.
    3 If no such file is found, it checks for the file logback.xml in the classpath..
    4 If no such file is found, and the executing JVM has the ServiceLoader (JDK 6 and above) the ServiceLoader will be used to resolve an implementation of com.qos.logback.classic.spi.Configurator. The first implementation found will be used. See ServiceLoader documentation for more details
    5 If none of the above succeeds, logback configures itself automatically using the BasicConfigurator which will cause logging output to be directed to the console.
    6 The fourth and last step is meant to provide a default (but very basic) logging functionality in the absence of a configuration file

      也可以在类路径上加一个类似如下的logback.xml的配置文件,logback则会去解析对应的配置文件。

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <configuration>
     3 
     4   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     5     <encoder>
     6       <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
     7     </encoder>
     8   </appender>
     9 
    10   <root level="DEBUG">          
    11     <appender-ref ref="STDOUT" />
    12   </root>  
    13   
    14 </configuration>

      4.3、使用过程简单分析

      • slf4j与底层的日志系统进行绑定在jar包中寻找org/slf4j/impl/StaticLoggerBinder.class 这个类,如在logback-classic中就含有这个类,如果找到多个StaticLoggerBinder,则表明目前底层有多个实际的日志框架,slf4j会随机选择一个。
      • 使用上述找到的StaticLoggerBinder创建一个实例,并返回一个LoggerFactory实例:
    1 return StaticLoggerBinder.getSingleton().getLoggerFactory()

          以logback-classic中的StaticLoggerBinder为例,在StaticLoggerBinder.getSingleton()过程中:会去加载解析配置文件 源码如下

     1 public URL findURLOfDefaultConfigurationFile(boolean updateStatus) {
     2     ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this);
     3     //寻找logback.configurationFile的系统属性
     4     URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);
     5     if (url != null) {
     6       return url;
     7     }
     8     //寻找logback.groovy
     9     url = getResource(GROOVY_AUTOCONFIG_FILE, myClassLoader, updateStatus);
    10     if (url != null) {
    11       return url;
    12     }
    13     //寻找logback-test.xml
    14     url = getResource(TEST_AUTOCONFIG_FILE, myClassLoader, updateStatus);
    15     if (url != null) {
    16       return url;
    17     }
    18     //寻找logback.xml
    19     return getResource(AUTOCONFIG_FILE, myClassLoader, updateStatus);
    20 }

        目前路径都是定死的,只有logback.configurationFile的系统属性是可以更改的,所以如果我们想更改配置文件的位置(不想放在类路径下),则需要设置这个系统属性:

    1 System.setProperty("logback.configurationFile", "/path/to/config.xml");

        解析完配置文件后,返回的LoggerFactory实例的类型是LoggerContext(它包含了配置信息)

      • 根据返回的LoggerFactory实例,来获取Logger就是根据上述的LoggerContext来创建一个Logger,每个logger与LoggerContext建立了关系,并放到LoggerContext的缓存中,就是LoggerContext的如下属性:

    1 private Map<String, Logger> loggerCache;

        其实上述过程就是slf4j与其他日志系统的绑定过程。不同的日志系统与slf4j集成,都会有一个StaticLoggerBinder类,并会拥有一个LoggerFactory的实现。

        

  • 相关阅读:
    mysql source命令可以导入比较大的文件
    开源 小程序
    React-Native项目在Android真机上调试
    react-native中长度单位换算
    webpack 去console
    微信H5移动端真机调试--vConsole
    记录
    盘点ES7、ES8、ES9、ES10新特性
    Mach-o可执行文件简述
    堆排序算法
  • 原文地址:https://www.cnblogs.com/ouhouki/p/10103987.html
Copyright © 2011-2022 走看看