Java Spring 使用AOP代理方法 型別轉換異常java.lang.ClassCastException 原因及解決辦法
阿新 • • 發佈:2021-01-29
有一段程式碼 有時會出現型別轉換異常 很詭異 排查原因發現是spring aop造成的。
專案中我使用了aop進行自定義許可權,若許可權不通過 返回固定的ResponseVo 對應欄位為:
@Data @AllArgsConstructor @NoArgsConstructor public class ResponseVo<T> { @JsonProperty("response_code") private Integer responseCode; @JsonProperty("verbose_msg") private String verboseMsg; private T data; }
為了開發方便 不需要每個controller都寫一個ResponseVo的構建 使用了ResponseBodyAdvice來幫助構建,之前的文章裡寫過
說白了就說Controller方法只需要返回一個任意物件由spring將其封裝到ResponseVo的data欄位中。
下面的是使用ResponseBodyAdvice的效果 上面是正常寫法
這個介面比較簡單可能沒太大對比度
但是在鑑權的aop中 若許可權通過則呼叫方法 返回方法結果
若不通過 則返回內容為:是一個ResponseVo
報錯內容為 不能把ResponseVo轉為BaseInfoVo,且堆疊中看不出任何自己寫的程式碼引用。
測試時發現 有許可權時 這個介面不報錯,沒有許可權時就會報型別轉換異常。找到這個規律 就很容易知道問題出在哪了。
原因是: spring在代理這個方法時 知道這個方法宣告的返回值為BaseInfoVo,但當權限不通過時 我通過切面將其返回值改為了ResponseVo,但R不能轉為B 就會報型別轉換異常。
解決辦法有2種:
1 Controller的返回型別統一為ResponseVo,這樣就沒辦法使用ResponseBodyAdvice了。
2 將方法的返回值宣告為所有可能被返回型別的共同介面:1 Object 因為Object是所有類的父類 2或宣告一個介面由R和Q分別實現 但這樣做意義不大。 缺點是返回值都為Object的話 語義不明確
最終選用了方法1