All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xiaoleilu.hutool.lang.Caller Maven / Gradle / Ivy

package com.xiaoleilu.hutool.lang;

import com.xiaoleilu.hutool.exceptions.UtilException;

/**
 * 调用者。可以通过此类的方法获取调用者、多级调用者以及判断是否被调用
 * 
 * @author Looly
 * @since 3.0.9
 */
public class Caller {
	private static final ICaller CALLER_INSTANCE;
	static {
		CALLER_INSTANCE = tryCreateCaller();
	}
	
	/**
	 * 获得调用者
	 * 
	 * @return 调用者
	 */
	public static Class getCaller() {
		return CALLER_INSTANCE.getCaller();
	}
	
	/**
	 * 获得调用者的调用者
	 * 
	 * @return 调用者的调用者
	 */
	public static Class getCallerCaller() {
		return CALLER_INSTANCE.getCallerCaller();
	}

	/**
	 * 获得调用者,指定第几级调用者
* 调用者层级关系: *
	 * 0 {@link Caller}
	 * 1 调用{@link Caller}中方法的类
	 * 2 调用者的调用者
	 * ...
	 * 
* * @param depth 层级。0表示{@link Caller}本身,1表示调用{@link Caller}的类,2表示调用者的调用者,依次类推 * @return 第几级调用者 */ public static Class getCaller(int depth) { return CALLER_INSTANCE.getCaller(depth); } /** * 是否被指定类调用 * * @param clazz 调用者类 * @return 是否被调用 */ public static boolean isCalledBy(Class clazz) { return CALLER_INSTANCE.isCalledBy(clazz); } /** * 尝试创建{@link ICaller}实现 * * @return {@link ICaller}实现 */ private static ICaller tryCreateCaller() { ICaller caller; try { caller = new ReflectionCaller(); } catch (Exception e) { try { caller = new SecurityManagerCaller(); } catch (Exception e2) { caller = new StackTraceCaller(); } } return caller; } // ---------------------------------------------------------------------------------------------- static interface and class /** * 调用者接口
* 可以通过此接口的实现类方法获取调用者、多级调用者以及判断是否被调用 * * @author Looly * */ private static interface ICaller { /** * 获得调用者 * * @return 调用者 */ Class getCaller(); /** * 获得调用者的调用者 * * @return 调用者的调用者 */ Class getCallerCaller(); /** * 获得调用者,指定第几级调用者 * 调用者层级关系: *
		 * 0 {@link Caller}
		 * 1 调用{@link Caller}中方法的类
		 * 2 调用者的调用者
		 * ...
		 * 
* * @param depth 层级。0表示{@link Caller}本身,1表示调用{@link Caller}的类,2表示调用者的调用者,依次类推 * @return 第几级调用者 */ Class getCaller(int depth); /** * 是否被指定类调用 * * @param clazz 调用者类 * @return 是否被调用 */ boolean isCalledBy(Class clazz); } /** * {@link SecurityManager} 方式获取调用者 * * @author Looly */ private static class SecurityManagerCaller extends SecurityManager implements ICaller { private static final int OFFSET = 1; @Override public Class getCaller() { return getClassContext()[OFFSET +1]; } @Override public Class getCallerCaller() { return getClassContext()[OFFSET +2]; } @Override public Class getCaller(int depth) { final Class[] context = getClassContext(); if ((OFFSET + depth) < context.length) { return context[OFFSET + depth]; } return null; } @Override public boolean isCalledBy(Class clazz) { final Class[] classes = getClassContext(); for (Class contextClass : classes) { if (contextClass.equals(clazz)) { return true; } } return false; } } /** * 通过sun.reflect.Reflection 获取调用者 * * @author Looly * */ @SuppressWarnings({ "deprecation", "restriction" }) private static class ReflectionCaller extends SecurityManagerCaller { private static final int OFFSET = 2; @Override public Class getCaller() { return sun.reflect.Reflection.getCallerClass(OFFSET + 1); } @Override public Class getCallerCaller() { return sun.reflect.Reflection.getCallerClass(OFFSET + 2); } @Override public Class getCaller(int depth) { return sun.reflect.Reflection.getCallerClass(OFFSET + depth); } } /** * 通过StackTrace方式获取调用者。此方式效率最低,不推荐使用 * * @author Looly */ private static class StackTraceCaller implements ICaller { private static final int OFFSET = 2; @Override public Class getCaller() { final String className = Thread.currentThread().getStackTrace()[OFFSET + 1].getClassName(); try { return Class.forName(className); } catch (ClassNotFoundException e) { throw new UtilException(e, "[{}] not found!", className); } } @Override public Class getCallerCaller() { final String className = Thread.currentThread().getStackTrace()[OFFSET + 2].getClassName(); try { return Class.forName(className); } catch (ClassNotFoundException e) { throw new UtilException(e, "[{}] not found!", className); } } @Override public Class getCaller(int depth) { final String className = Thread.currentThread().getStackTrace()[OFFSET + depth].getClassName(); try { return Class.forName(className); } catch (ClassNotFoundException e) { throw new UtilException(e, "[{}] not found!", className); } } @Override public boolean isCalledBy(Class clazz) { for (final StackTraceElement element : Thread.currentThread().getStackTrace()) { if (element.getClassName().equals(clazz.getName())) { return true; } } return false; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy