背景
由於想記錄 controller 前後的處理情況,為什麼不用 filter 處理是因為專案中有作業等其他請求,並不想做太多記錄。
問題描述
加了 @aspect 註解在切面類上,
/**
* 記錄controller方法前所有的日誌
** @param joinpoint 不能為空
*/@before("execution(* com.***.controller..*.*(..))")
public void pointbeforemethodinvoke(joinpoint joinpoint)
然後我們的包結構如下:(xx 是把關鍵字隱去了)
可以看到我的切面是切的 controller 以及它下面的子包 api 和相關的類。
問題爆發,測試的時候發現,controller 和它下面子包的 api 除了乙個類,其他的類都能被切面處理,唯獨某個 controller 進不去,而且詭異的是 在該類中注入的 service 類全為 null。 然後爆發了空指標異常。
在爆發了空指標後,首先第一反應就是切面是否正常,檢視 execution 表示式,以及測試 controller 下的其他類,正常,所以排除 切面類的問題
在某個空指標的地方 debug,然後手動獲取 注入的 service 的 bean,發現正常,證明相關的配置註解正常。
在想不到其他辦法的時候,選擇使用 @postconstruct 。在出問題的 controller 中加入 init 手動初始化,加入 bean
public class statisticscontroller
然後在 init 方法中 debug, 發現在 spring 啟動的時候,statisticsservice 和 knowledgeservice 注入正常,但是在請求 controller 的時候,2 個 service 還是 null。
在嘗試完上訴方法,想不到辦法的情況下,只能上大招了(原諒作者菜)。一行一行的和正常的模擬較**,
當然,結果出來了,發現出問題的 controller 的方法都是 private 的,正常的都是 public 的,然後查詢相關的 文件,找到了原因
與aspectj相比,spring aop是一種基於**的「aop lite」方法。它僅適用於spring元件,僅適用於公共,非靜態方法。這在spring aop文件中也有解釋,如下所示:
由於spring的aop框架基於**的特性,受保護的方法根據定義不會被攔截,既不用於jdk**(這不適用),也不用於cglib**(這在技術上可行,但不建議用於aop)。因此,任何給定的切入點都只能與公共方法匹配!如果您的攔截需要包括受保護/私有方法甚至建構函式,請考慮使用spring驅動的本機aspectj編織而不是spring的基於**的aop框架。這構成了具有不同特徵的不同aop使用模式,因此在做出決定之前一定要先熟悉編織。說白了 就是 aop底層是**,
jdk是**介面,私有方法必然不會存在在介面裡,所以就不會被攔截到;
cglib是子類,private的方法照樣不會出現在子類裡,也不能被攔截。
不是類內部直接呼叫方法,而是通過維護乙個自身例項的**
所以 execution(public * com.***.controller...(..))) 只會切 public 的方法,不寫也一樣,public 是預設切的方法,如果寫了protected,他就什麼事情都不做,連protected的方法也不攔截。
如果想要實現攔截private方法的 可以使用 原生 aspectj 編譯期/執行期織入。
而我們上面的空指標問題,其實就是 切面已經**了 controller 下的類,但是又沒有被切到,造成了注入的失敗。
spring 切面程式設計
spring aop就是乙個同心圓,要執行的方法為圓心,最外層的order最小。從最外層按照aop1 aop2的順序依次執行doaround方法,dobefore方法。然後執行method方法,最後按照aop2 aop1的順序依次執行doafter doafterreturn方法。也就是說對多個ao...
spring 切面例子
org.springframeworkgroupid spring contextartifactid 5.1.6.releaseversion dependency org.springframeworkgroupid spring aspectsartifactid 5.1.6.releasev...
Spring面向切面程式設計
1 面向切面程式設計 aop 的概念 把專案中需要在多處用到的功能,比如日誌 安全和事物等集中到乙個類中處理,而不用在每個需要用到該功能的地方顯式呼叫。2 術語解釋 橫切關注點 分布應用於多處的功能 切面 橫切關注點可以被模組化為乙個類,這個類被稱為乙個切面 通知 advice 切面要完成的工作。s...