logback的使用和原理

打印 上一主题 下一主题

主题 1801|帖子 1801|积分 5403

logback的使用和原理

1 依赖关系

在pom文件中引入springboot starter依赖,自动引入了这三个依赖,而这三个依赖,就是logback日志框架进行日志操作的。
  1.     <dependencies>
  2.         <dependency>
  3.             <groupId>org.springframework.boot</groupId>
  4.             <artifactId>spring-boot-starter</artifactId>
  5.         </dependency>
  6.     </dependencies>
复制代码


可以看到,logback-classic依赖于logback-core和slf4j-api。
2 执行流程

当我们在一个类中,使用 LoggerFactory.getLogger(xxx.class) 获取一个类的 Logger 对象时,发生了什么事是在什么时候加载的logback.xml文件中的配置的,这是本文要解决的问题
  1. package org.example;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import java.util.Date;
  5. import java.util.UUID;
  6. public class LogPathOnLinuxApp
  7. {
  8.     private static final Logger logger =  LoggerFactory.getLogger(LogPathOnLinuxApp.class);
  9.     public static void main(String[] args) {
  10.         logger.info(new Date().toString() + "生成了 UUID: " + UUID.randomUUID());
  11.     }
  12. }
复制代码
单独的 T 代表一个类型 ,而 Class代表这个类型所对应的类, Class表示类型不确定的类,Class表示类型不确定的类是A的子类
常见的调用方式,使用 LoggerFactory.getLogger(LogPathOnLinuxApp.class) 获取 Logger 对象,然后使用 logger.info() 使用日志框架,输出日志信息。
首先,从 LoggerFactory.getLogger入手,他位于 org.slf4j 包中
LoggerFactory 类中,
  1. // 1.1 使用时传入的class对象,调用的是这个方法
  2. public static Logger getLogger(Class<?> clazz) {
  3.         // 1.2 调用上面的方法,传入一个String类型的class的名字,返回一个Logger对象,这个就是最终返回的Logger对象,ctrl+鼠标左键,点进去
  4.         Logger logger = getLogger(clazz.getName());
  5.         if (DETECT_LOGGER_NAME_MISMATCH) {
  6.             Class<?> autoComputedCallingClass = Util.getCallingClass();
  7.             if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
  8.                 Util.report(String.format("Detected logger name mismatch. Given name: "%s"; computed name: "%s".", logger.getName(), autoComputedCallingClass.getName()));
  9.                 Util.report("See http://www.slf4j.org/codes.html#loggerNameMismatch for an explanation");
  10.             }
  11.         }
  12.                 // 最终返回给调用者的logger
  13.         return logger;
  14.     }
  15. // 1.2
  16. public static Logger getLogger(String name) {
  17.             // 1.3 调用getILoggerFactory方法,返回一个ILoggerFactory对象,点进去
  18.         ILoggerFactory iLoggerFactory = getILoggerFactory();
  19.             // 最终返回iLoggerFactory.getLogger(name)的Logger对象
  20.         return iLoggerFactory.getLogger(name);
  21.     }
  22. // 这是类中的静态变量,在类加载的时候初始化
  23. static final int UNINITIALIZED = 0; // 未初始化
  24. static final int ONGOING_INITIALIZATION = 1; // 正在初始化
  25. static final int FAILED_INITIALIZATION = 2; // 初始化失败
  26. static final int SUCCESSFUL_INITIALIZATION = 3; // 初始化成功
  27. static final int NOP_FALLBACK_INITIALIZATION = 4; // 无回退初始化
  28. static volatile int INITIALIZATION_STATE = 0; // 初始化状态
  29. // 1.3
  30. public static ILoggerFactory getILoggerFactory() {
  31.             // 如果未初始化,就进行初始化操作
  32.         if (INITIALIZATION_STATE == 0) {
  33.             Class var0 = LoggerFactory.class;
  34.             // 对LoggerFactory类加锁
  35.             synchronized(LoggerFactory.class) {
  36.                 // 如果未初始化,将状态设置为正在初始化,执行performInitialization()
  37.                 if (INITIALIZATION_STATE == 0) {
  38.                     INITIALIZATION_STATE = 1;
  39.                     // 执行初始化
  40.                     performInitialization();
  41.                 }
  42.             }
  43.         }
  44.                 // 判断初始化状态
  45.         switch (INITIALIZATION_STATE) {
  46.             case 1:
  47.                 return SUBST_FACTORY;
  48.             case 2:
  49.                 throw new IllegalStateException("org.slf4j.LoggerFactory in failed state. Original exception was thrown EARLIER. See also http://www.slf4j.org/codes.html#unsuccessfulInit");
  50.             // 如果初始化成功,返回 StaticLoggerBinder.getSingleton().getLoggerFactory();
  51.             case 3:
  52.                 // 1.4 看这个方法 getLoggerFactory
  53.                 return StaticLoggerBinder.getSingleton().getLoggerFactory();
  54.             case 4:
  55.                 return NOP_FALLBACK_FACTORY;
  56.             default:
  57.                 throw new IllegalStateException("Unreachable code");
  58.         }
  59.     }
复制代码
StaticLoggerBinder 类中,
  1. private static StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
  2. private LoggerContext defaultLoggerContext = new LoggerContext();
  3. static {
  4.         SINGLETON.init();
  5.     }
  6. void init() {
  7.         try {
  8.             try {
  9.                 // 自动配置,autoConfig 点进去
  10.                 (new ContextInitializer(this.defaultLoggerContext)).autoConfig();
  11.             } catch (JoranException var2) {
  12.                 Util.report("Failed to auto configure default logger context", var2);
  13.             }
  14.             if (!StatusUtil.contextHasStatusListener(this.defaultLoggerContext)) {
  15.                 StatusPrinter.printInCaseOfErrorsOrWarnings(this.defaultLoggerContext);
  16.             }
  17.             this.contextSelectorBinder.init(this.defaultLoggerContext, KEY);
  18.             this.initialized = true;
  19.         } catch (Exception var3) {
  20.             Util.report("Failed to instantiate [" + LoggerContext.class.getName() + "]", var3);
  21.         }
  22.     }
复制代码
ContextInitializer 类中,
  1. // 此处的静态常量,表示的是logback的配置文件名
  2. public static final String AUTOCONFIG_FILE = "logback.xml";
  3. public static final String TEST_AUTOCONFIG_FILE = "logback-test.xml";
  4. public static final String CONFIG_FILE_PROPERTY = "logback.configurationFile";
  5. final LoggerContext loggerContext;
  6. //
  7. public void autoConfig() throws JoranException {
  8.         StatusListenerConfigHelper.installIfAsked(this.loggerContext);
  9.             // 没有任何配置文件时url为null
  10.         URL url = this.findURLOfDefaultConfigurationFile(true);
  11.         if (url != null) {
  12.             // 读取自定义的配置文件,logback.xml文件配置生效
  13.             this.configureByResource(url);
  14.         } else {
  15.             Configurator c = (Configurator)EnvUtil.loadFromServiceLoader(Configurator.class);
  16.             if (c != null) {
  17.                 try {
  18.                     c.setContext(this.loggerContext);
  19.                     c.configure(this.loggerContext);
  20.                 } catch (Exception var4) {
  21.                     throw new LogbackException(String.format("Failed to initialize Configurator: %s using ServiceLoader", c != null ? c.getClass().getCanonicalName() : "null"), var4);
  22.                 }
  23.             } else {
  24.                 // 这一段代码保证了,没有任何配置文件时,也可以进行基础的自动配置,进行日志输出
  25.                 BasicConfigurator basicConfigurator = new BasicConfigurator();
  26.                 basicConfigurator.setContext(this.loggerContext);
  27.                 basicConfigurator.configure(this.loggerContext);
  28.             }
  29.         }
  30.     }
复制代码
3 日志滚动配置

需要注意在linux下执行的路径问题
  1. <configuration>
  2.    
  3.        
  4.    
  5.         <contextListener  />
  6.     <appender name="dailyRollingFileAppender" >
  7.         <File>${LOG_PATH}/${PROJECT_NAME}/logs/LogsPathTest.log</File>
  8.         <rollingPolicy >
  9.             
  10.             <FileNamePattern>${LOG_PATH}/${PROJECT_NAME}/logs/LogsPathTest.%d{yyyy-MM-dd}.%i.log.gz</FileNamePattern>
  11.             
  12.             <MaxHistory>15</MaxHistory>
  13.             
  14.             <MaxFileSize>2MB</MaxFileSize>
  15.         </rollingPolicy>
  16.         <encoder>
  17.             <Pattern>%date{yyyy-MM-dd HH:mm:ss}\t%level\t%logger{96}\t%msg%n</Pattern>
  18.         </encoder>
  19.         <filter >
  20.             <level>INFO</level>
  21.         </filter>
  22.     </appender>
  23.    
  24.     <appender name="STDOUT" >
  25.         
  26.         <encoder>
  27.             <Pattern>%date{yyyy-MM-dd HH:mm:ss}\t%level\t%logger{96}\t%msg%n</Pattern>
  28.         </encoder>
  29.         <filter >
  30.             <level>INFO</level>
  31.         </filter>
  32.     </appender>
  33.     <root level="INFO">
  34.         <appender-ref ref="dailyRollingFileAppender"/>
  35.         <appender-ref ref="STDOUT"/>
  36.     </root>
  37. </configuration>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

西河刘卡车医

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表