前言
当我们在使用日志框架的时候,每个类都要通过工厂方法获取一个日志对象来打印日志,感觉太麻烦了。所以想着去封装一个日志静态类。但是问题是封装的那个静态日志类打印出的类信息都是日志类自己,这肯定不是我们想要的啊,我们需要的是当前调用打印日志的这个类的信息啊。
开始思考
我们发现平时使用的Logback等日志框架能准确捕获源代码的所在的类、方法、行。但java并没有提供相应的方法,这似乎很神奇。其实Logback是通过java错误堆栈来实现的,也就是说通过new一个异常Throwable,然后再捕获,从而得到堆栈信息,在进行分析就可以得到行号等信息了。
我们可以借鉴这种思想,在静态日志类中,获取当前线程的堆栈信息,然后找到实际调用者。JDK的Thread类提供了一个getStackTrace()可以获取线程的堆栈跟踪链。下面来看一下这个方法。
/**
* 返回一个表示该线程堆栈转储的堆栈跟踪元素数组。如果该线程尚未启动或已经终止,则该方法将返回一个零长度数组。
* 如果返回的数组不是零长度的,则其第一个元素代表堆栈顶,它是该序列中最新的方法调用。最后一个元素代表堆栈底,是该序列中最旧的方法调用。
*/
public StackTraceElement[] getStackTrace() {
// 如果该线程不是当前线程
if (this != Thread.currentThread()) {
// 获取安全管理器
SecurityManager security = System.getSecurityManager();
// 如果有安全管理器
if (security != null) {
// 检查是否有权限获取堆栈跟踪
security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);
}
// 如果线程未启动或已终止,则不会获取堆栈跟踪信息,直接返回一个空堆栈