AOP通過連接點獲取Method異常 java.lang.NoSuchMethodException
問題
在用AOP做日誌的時候,出現了java.lang.NoSuchMethodException無法獲得Method的異常。
原方法
<code>/**
* 獲取日誌註解參數
* @param joinPoint
* @return
* @Date 2018年11月7日 下午3:52:54
* @Author lay
*/
public LogApi getLogApi(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
Class>[] argTypes = new Class[joinPoint.getArgs().length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = args[i].getClass();
}
Method method = null;
try {
method = joinPoint.getTarget().getClass().getMethod(joinPoint.getSignature().getName(), argTypes);
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (SecurityException e) {
e.printStackTrace();
}
LogApi logApi = method.getDeclaredAnnotation(LogApi.class);
return logApi;
}/<code>
原本是通過連接點JoinPoint獲得目標對象方法的參數和方法名,在通過目標對象的getMethod的方法獲得Method對象。
這段代碼在我剛寫完的測試中是沒有問題的,但是在標註到下面的方法上就拋出了NoSuchMethodException異常。
<code>@Override
@LogApi(logType = SysLogType.SYS_STAFF_OPER_LOG, systemType = SystemType.SYSTEM_TYPE_SYSMANM, comandType = Operation.FIND_PASSWROD)
public String updateFindPassword(Map map) {
//..具體方法省略
}/<code>
這裡是通過Postman進行模擬參數測試的。
原因
在通過幾次測試後,我發現問題出現在方法的參數上。
為了測試,我將原代碼參數類型寫成Map.class
<code> method = joinPoint.getTarget().getClass().getMethod(joinPoint.getSignature().getName(), Map.class);/<code>
這樣就沒有問題。
經過打斷點發現,postman模擬的Map參數自動實例化成LinkedHashMap,那麼我通過遍歷參數獲得參數的class類型時就是LinkedHashMap.class而不是Map.class,這樣我根據參數類型LinkedHashMap.class去獲得方法就會報出java.lang.NoSuchMethodException異常。
解決辦法
使用 MethodSignature的getMethod()方法。
修改代碼如下
<code> /**
* 獲取日誌註解參數
* @param joinPoint
* @return
* @Date 2018年11月7日 下午3:52:54
* @Author lay
*/
public LogApi getLogApi(JoinPoint joinPoint) throws NoSuchMethodException {
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
Method method = null;
method = methodSignature.getMethod();
LogApi logApi = method.getDeclaredAnnotation(LogApi.class);
return logApi;
}/<code>
這樣就好了。
閱讀更多 Sadlay 的文章