当前位置:   article > 正文

Java简单模拟Slf4j log4j 使用可变参数打印日志_slf4j如何打印可变参数

slf4j如何打印可变参数

关键词:Slf4j、log4j、可变参数、源码、懒加载、正则

想在打印日志后重复使用要输出的日志结果,所以想封装一下Slf4j可变参数打印的方法,同时拿到打印结果字符串;

本来思路很简单,将可变参数依次填入占位符即可,但是想看看Slf4j是怎么实现的,中间遇到了些问题,记录一下。

1、简单实现

暂时没有想到好方法通过输入的日志级别来动态调用log.info log.error等方法,所以写了三种不同级别的方法;

  FILL_STRING用来判断是否还有未填充的占位符;FILL_FORMAT用来做String.replaceFirst的入参,表示正则表达式匹配"{}"的;

  1. private static final String FILL_STRING = "{}";
  2. private static final String FILL_FORMAT = "\\{\\}";
  3. public static void info(String format, Object... argument) {
  4. log.info(format, argument);
  5. String logInfo = getLog(format, argument);
  6. System.out.println("log is " + logInfo);
  7. }
  8. public static void error(String format, Object... argument) {
  9. log.error(format, argument);
  10. String logInfo = getLog(format, argument);
  11. System.out.println("log is " + logInfo);
  12. }
  13. public static void warn(String format, Object... argument) {
  14. log.warn(format, argument);
  15. String logInfo = getLog(format, argument);
  16. System.out.println("log is " + logInfo);
  17. }
  18. private static String getLog(String format, Object[] arg) {
  19. // 防止空指针
  20. if (arg == null) {
  21. if (!format.contains(FILL_STRING)) {
  22. return format;
  23. }
  24. return format.replaceFirst(FILL_FORMAT, "null");
  25. }
  26. StringBuilder formatBuilder = new StringBuilder(format);
  27. for (Object anArg : arg) {
  28. // 打印异常堆栈信息
  29. if (anArg instanceof Throwable) {
  30. Throwable temp = (Throwable) anArg;
  31. formatBuilder.append(temp.toString()).append("\n");
  32. StackTraceElement[] stackTrace = temp.getStackTrace();
  33. for (StackTraceElement aStackTrace : stackTrace) {
  34. formatBuilder.append(aStackTrace).append("\n");
  35. }
  36. continue;
  37. }
  38. formatBuilder = new StringBuilder(formatBuilder.toString().replaceFirst(FILL_FORMAT, anArg == null ? "null" : anArg.toString()));
  39. }
  40. format = formatBuilder.toString();
  41. return format;
  42. }

2、查看Slf4j源码

跟踪调用链,跟到org.apache.logging.log4j.core.impl.Log4jLogEvent#Log4jLogEvent构造方法,第412行 

this.message = message;

这句话执行前,message对象的formattedMessage还是null,执行后值就变成填充后的数据了;

刚开始还不能理解,一个赋值操作为什么右边的对象值会改变,后来才知道因为message对象是懒加载,在赋值的时候调用getFormattedMessage方法,如果值为null就进行填充可变参数操作。

附上源码:

  1. public String getFormattedMessage() {
  2. if (formattedMessage == null) {
  3. final StringBuilder buffer = getThreadLocalStringBuilder();
  4. // 这里填充可变参数
  5. formatTo(buffer);
  6. formattedMessage = buffer.toString();
  7. StringBuilders.trimToMaxSize(buffer, Constants.MAX_REUSABLE_MESSAGE_SIZE);
  8. }
  9. return formattedMessage;
  10. }
  11. @Override
  12. public void formatTo(final StringBuilder buffer) {
  13. if (formattedMessage != null) {
  14. buffer.append(formattedMessage);
  15. } else {
  16. if (indices[0] < 0) {
  17. ParameterFormatter.formatMessage(buffer, messagePattern, argArray, usedCount);
  18. } else {
  19. ParameterFormatter.formatMessage2(buffer, messagePattern, argArray, usedCount, indices);
  20. }
  21. }
  22. }
  23. /**
  24. * Replace placeholders in the given messagePattern with arguments.
  25. *
  26. * @param buffer the buffer to write the formatted message into
  27. * @param messagePattern the message pattern containing placeholders.
  28. * @param arguments the arguments to be used to replace placeholders.
  29. */
  30. static void formatMessage2(final StringBuilder buffer, final String messagePattern,
  31. final Object[] arguments, final int argCount, final int[] indices) {
  32. if (messagePattern == null || arguments == null || argCount == 0) {
  33. buffer.append(messagePattern);
  34. return;
  35. }
  36. int previous = 0;
  37. for (int i = 0; i < argCount; i++) {
  38. buffer.append(messagePattern, previous, indices[i]);
  39. previous = indices[i] + 2;
  40. recursiveDeepToString(arguments[i], buffer, null);
  41. }
  42. buffer.append(messagePattern, previous, messagePattern.length());
  43. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/915795
推荐阅读
相关标签
  

闽ICP备14008679号