Java获取自身被调用点

1. 场景

打印日志的时候,需要获取是在哪个地方被调用了,把调用点的信息一并打印出来。

2. 获取自身被调用点的方法

可以通过获取线程的调用栈,遍历后找到调用点。

3. 代码实现

import java.lang.management.ManagementFactory;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

public class Log {
    private static final String INFO = "INFO";
    private static final String WARN = "WARN";
    private static final String ERROR = "ERROR";
    private static final String DEBUG = "DEBUG";
    private static final String EMPTY = "";
    private static final String DEFAULT = "\033[0m%s\033[0m";
    private static final String FONT_GREEN = "\033[32m%s\033[0m";
    private static final String FONT_YELLOW = "\033[33m%s\033[0m";
    private static final String FONT_RED = "\033[31m%s\033[0m";
    private static final String FONT_MAGENTA = "\033[35m%s\033[0m";
    private static final String FONT_CYAN = "\033[36m%s\033[0m";


    private static final String SELF_CLASS_NAME = Log.class.getName();
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
    private static final ZoneId ZONE_ID = ZoneId.systemDefault();
    private static String pid;

    static {
        String name = ManagementFactory.getRuntimeMXBean().getName();
        pid = createColorfulStr(name.split("@")[0], FONT_MAGENTA);
    }

    private static StackTraceElement findCallPoint() {
        Thread currentThread = Thread.currentThread();
        StackTraceElement[] stackTraces = currentThread.getStackTrace();
        boolean isFrontOfLogClass = true;
        for (StackTraceElement stackTrace : stackTraces) {
            if (SELF_CLASS_NAME.equals(stackTrace.getClassName())) {
                isFrontOfLogClass = false;
                continue;
            }
            if (isFrontOfLogClass) {
                continue;
            }
            return stackTrace;
        }
        return null;
    }

    private static String getMsgPrefix(String msgType) {
        StackTraceElement callPoint = findCallPoint();
        if (callPoint == null) {
            return "-";
        }
        String timeStamp = LocalDateTime.now().atZone(ZONE_ID).format(DATE_TIME_FORMATTER);
        String threadName = Thread.currentThread().getName();
        String className = callPoint.getClassName();
        String fileName = callPoint.getFileName();
        int lineNumber = callPoint.getLineNumber();
        String methodName = callPoint.getMethodName();
        StringBuffer sb = new StringBuffer();
        sb.append(timeStamp)
                .append(" ")
                .append(createColorfulStr(msgType))
                .append(" ")
                .append(pid)
                .append(" --- [")
                .append(threadName)
                .append("] at ")
                .append(createColorfulStr(String.format("%s.%s(%s:%d) ", className, methodName, fileName, lineNumber), FONT_CYAN));
        return sb.toString();
    }

    private static String createColorfulStr(String str) {
        return createColorfulStr(str, null);
    }

    private static String createColorfulStr(String str, String color) {
        if (color == null) {
            color = DEFAULT;
        }
        if (str == null) {
            str = EMPTY;
        }
        switch (str) {
            case DEBUG:
                return String.format(FONT_GREEN, DEBUG);
            case INFO:
                return String.format(FONT_GREEN, " " + INFO);
            case WARN:
                return String.format(FONT_YELLOW, " " + WARN);
            case ERROR:
                return String.format(FONT_RED, ERROR);
        }
        return String.format(color, str);
    }

    public static void info(String msg) {
        System.out.println(getMsgPrefix(INFO) + msg);
    }

    public static void warn(String msg) {
        System.out.println(getMsgPrefix(WARN) + msg);
    }

    public static void error(String msg) {
        System.out.println(getMsgPrefix(ERROR) + msg);
    }

    public static void debug(String msg) {
        System.out.println(getMsgPrefix(DEBUG) + msg);
    }
}

4. 测试

测试代码:

public class Test {
    public static void main(String[] args) {
        Log.info("=====testLog main=====");
        testLog();
    }

    private static void testLog() {
        Log.info("=====testLog info=====");
        Log.warn("=====testLog warn=====");
        Log.error("=====testLog error=====");
        Log.debug("=====testLog debug=====");
    }
}

控制台输出:

2025-04-22T00:49:28.443+08:00  INFO 26888 --- [main] at com.example.study.controller.Test.main(Test.java:5) =====testLog main=====
2025-04-22T00:49:28.449+08:00  INFO 26888 --- [main] at com.example.study.controller.Test.testLog(Test.java:10) =====testLog info=====
2025-04-22T00:49:28.449+08:00  WARN 26888 --- [main] at com.example.study.controller.Test.testLog(Test.java:11) =====testLog warn=====
2025-04-22T00:49:28.449+08:00 ERROR 26888 --- [main] at com.example.study.controller.Test.testLog(Test.java:12) =====testLog error=====
2025-04-22T00:49:28.449+08:00 DEBUG 26888 --- [main] at com.example.study.controller.Test.testLog(Test.java:13) =====testLog debug=====
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值