package org.test4j.tools.reflector; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import org.test4j.module.Test4JException; import org.test4j.tools.commons.ClazzHelper; import org.test4j.tools.commons.ExceptionWrapper; import org.test4j.tools.commons.MethodHelper; import org.test4j.tools.exception.NoSuchMethodRuntimeException; @SuppressWarnings({ "rawtypes", "unchecked" }) public class MethodAccessor<T> { private final Method method; private final Class targetClaz; public MethodAccessor(Class targetClaz, String methodName, Class... parametersType) { this.targetClaz = targetClaz; this.method = MethodHelper.getMethod(targetClaz, methodName, parametersType); } /** * * @param targetObj * @param targetClazz * @param methodName * @param parametersType */ public MethodAccessor(Object target, String methodName, Class... parametersType) { this.targetClaz = target.getClass(); this.method = MethodHelper.getMethod(targetClaz, methodName, parametersType); } public MethodAccessor(Method method) { this.method = method; this.targetClaz = method.getDeclaringClass(); } public Method getMethod() { return this.method; } public T invoke(Object target, Object[] args) throws Exception { boolean isAccessible = this.method.isAccessible(); try { this.method.setAccessible(true); return (T) method.invoke(target, args); } catch (InvocationTargetException e) { Throwable te = e.getTargetException(); if (te instanceof Exception) { throw (Exception) te; } else { throw e; } } finally { this.method.setAccessible(isAccessible); } } /** * 调用方法,不显式抛出异常<br> * 原方法如果有显式异常,将被封装 * * @param target * @param args * @return */ public T invokeUnThrow(Object target, Object[] args) { try { return invoke(target, args); } catch (InvocationTargetException e) { Throwable targetException = e.getTargetException(); throw ExceptionWrapper.wrapWithRuntimeException(targetException); } catch (Throwable e) { throw ExceptionWrapper.wrapWithRuntimeException(e); } } public T invokeStatic(Object[] args) throws Exception { if (Modifier.isStatic(method.getModifiers()) == false) { String methodDesc = method.getName() + "(" + Arrays.toString(method.getParameterTypes()) + ")"; throw new NoSuchMethodRuntimeException("No such static method: " + methodDesc + " in class[" + this.targetClaz + "]"); } else { return (T) invoke(null, args); } } public T invokeStaticUnThrow(Object[] args) { try { return (T) invokeStatic(args); } catch (InvocationTargetException e) { Throwable targetException = e.getTargetException(); throw ExceptionWrapper.wrapWithRuntimeException(targetException); } catch (Throwable e) { throw ExceptionWrapper.wrapWithRuntimeException(e); } } /** * Invokes the given method with the given parameters on the given target * object * * @param target * The object containing the method, not null * @param method * The method, not null * @param arguments * The method arguments * @return The result of the invocation, null if void * @throws Test4JException * if the method could not be invoked */ public static <T> T invokeMethod(Object target, Method method, Object... arguments) throws Exception { boolean isAccessible = method.isAccessible(); try { method.setAccessible(true); return (T) method.invoke(target, arguments); } finally { method.setAccessible(isAccessible); } } public static <T> T invokeMethodUnThrow(Object target, Method method, Object... arguments) { if (method == null) { throw new RuntimeException("reflector invoke ,the argument[method] can't be null."); } try { return (T) invokeMethod(target, method, arguments); } catch (Exception e) { throw new Test4JException("Unable to invoke method[" + method.getName() + "].", e); } } public static <T> T invokeMethod(Object target, String methodNmae, Object... paras) throws Exception { if (target == null) { throw new RuntimeException("the target object can't be null!"); } Object _target = ClazzHelper.getProxiedObject(target); Class[] paraClazes = MethodHelper.getParameterClazz(paras); Method method = MethodHelper.getMethod(_target.getClass(), methodNmae, paraClazes); Object result = invokeMethod(_target, method, paras); return (T) result; } /** * 反射调用方法,不显式的抛出受检异常<br> * 原生的受检异常会被包装成运行时异常 * * @param <T> * @param target * @param methodName * @param paras * @return */ public static <T> T invokeMethodUnThrow(Object target, String methodName, Object... paras) { try { return (T) invokeMethod(target, methodName, paras); } catch (Exception e) { throw new Test4JException("Unable to invoke method[" + methodName + "].", e); } } }