AOP通過連接點獲取Method異常之空指針

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>

這樣就好了。


分享到:


相關文章: