springboot Bean提前加載未被BeanPostProcessor增強處理導致aop注解切面失效及解決辦法

前言

最近碰到個問題宾娜,公司項目中使用了shiro權限框架并自定義了UserRealm類侈百,現(xiàn)在我要在其中注入一個Service類缀旁,調用運行一個業(yè)務邏輯更扁,而這個方法上帶有aop注解切面盖腕。結果,這整個Service類內(nèi)的所有方法上帶有的切面都失效了浓镜,就很牛逼溃列,其他Service內(nèi)同個注解的切面則正常。

探索過程

然后我注意到在控制臺上有條關于UserRealm類的info日志膛薛,如下:

2020-11-20 17:09:59.856  INFO 11872 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'userRealm' of type [xxx.shiro.UserRealm] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

翻譯結果是:

類型為[xxx.shiro.UserRealm]的Bean'userRealm'不符合所有BeanPostProcessor的處理要求(例如:不符合自動代理的條件)

而且基本都是shiro模塊相關的類輸出的听隐,之前沒了解過BeanPostProcessor類,但大概意思可以理解哄啄,代理未生效雅任。

切面失效原因及BeanPostProcessor(后置處理器)類作用

BeanPostProcessor本身也是一個Bean,一般而言其實例化時機要早過普通的Bean咨跌。
百度后我明白了沪么,是因為UserRealm在BeanPostProcessor之前加載了,沒有被增強處理過導致的锌半。

執(zhí)行過程

從Application運行開始 -> ServletWebServerApplicationContext類的refresh() -> 父類AbstractApplicationContext的refresh() -> registerBeanPostProcessors() -> PostProcessorRegistrationDelegate類的靜態(tài)registerBeanPostProcessors()禽车。

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    // 注意:此處只會拿到Bean的定義信息~~~~
    // 已經(jīng)被實例化的Bean最終都會調用`beanFactory.addBeanPostProcessor`而緩存在AbstractBeanFactory的字段:beanPostProcessors里,它是個CopyOnWriteArrayList
    // 更重要的是:最終最終所有的BeanPostProcessor的執(zhí)行都會從這個List里面拿出來執(zhí)行
    // 所以這一步很關鍵:那就是按照順序刊殉,把`BeanPostProcessor`們都實例化好哭当,然后添加進List里
    // 因此順序是關鍵~~~~~如果某些Bean提前被實例化,它就很有可能不能被所有的`BeanPostProcessor`處理到了
    // 這也是我們BeanPostProcessorChecker的作用冗澈,它就是檢查這個然后輸出日志的~
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // 這個beanProcessorTargetCount此處賦值了钦勘,后續(xù)就都不會變了,BeanPostProcessorChecker就是和這個進行比較的~
    // beanFactory里面的Bean實例總個數(shù)+1(自己)+bean定義信息~
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 把BeanPostProcessorChecker加進去亚亲,它其實就是做了一個檢查而已~~~~~~~輸出一個info日志~
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // 1彻采、找到所有實現(xiàn)PriorityOrdered的`BeanPostProcessor`,然后getBean捌归,然后統(tǒng)一排序肛响,然后beanFactory.addBeanPostProcessor()
    // 2、處理實現(xiàn)Ordered的惜索,步驟同上
    // 3特笋、處理沒實現(xiàn)排序接口的普通的處理器,不需要sort了巾兆,直接add進去~

    // 最后注冊一個特殊的處理器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
BeanPostProcessor類數(shù)組

其中猎物,Bean被提前加載的info日志就是由BeanPostProcessorChecker類輸出的虎囚。


BeanPostProcessor類數(shù)組

這是最后添加完畢的BeanPostProcessor類數(shù)組。


postProcessorNames

postProcessorNames數(shù)組里的就是早于BeanPostProcessor加載的類蔫磨,UserRealm附帶于紅框內(nèi)的Bean淘讥。

解決方案

shiro模塊的Bean被提前加載是無法解決的,只能延遲其中注入的Service加載時間堤如。

@Autowired
@Lazy
private TestService testService;

如上蒲列,附上Spring的@Lazy注解就行了,或者使用@Autowired的required = "false"搀罢,然后在調用處主動校驗并從上下文獲取Service實例蝗岖。很明顯用@Lazy方便多了。

參考鏈接

【小家Spring】注意BeanPostProcessor啟動時對依賴Bean的“誤傷”陷阱(is not eligible for getting processed by all...)

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子跷究,更是在濱河造成了極大的恐慌,老刑警劉巖瓣俯,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杰标,死亡現(xiàn)場離奇詭異兵怯,居然都是意外死亡,警方通過查閱死者的電腦和手機腔剂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門媒区,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掸犬,你說我怎么就攤上這事袜漩。” “怎么了湾碎?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵宙攻,是天一觀的道長。 經(jīng)常有香客問我介褥,道長座掘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任柔滔,我火速辦了婚禮溢陪,結果婚禮上,老公的妹妹穿的比我還像新娘睛廊。我一直安慰自己形真,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布超全。 她就那樣靜靜地躺著咆霜,像睡著了一般邓馒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上裕便,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天绒净,我揣著相機與錄音,去河邊找鬼偿衰。 笑死挂疆,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的下翎。 我是一名探鬼主播缤言,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼视事!你這毒婦竟也來了胆萧?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤俐东,失蹤者是張志新(化名)和其女友劉穎跌穗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虏辫,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蚌吸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了砌庄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羹唠。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖娄昆,靈堂內(nèi)的尸體忽然破棺而出佩微,到底是詐尸還是另有隱情,我是刑警寧澤萌焰,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布哺眯,位于F島的核電站,受9級特大地震影響扒俯,放射性物質發(fā)生泄漏奶卓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一陵珍、第九天 我趴在偏房一處隱蔽的房頂上張望寝杖。 院中可真熱鬧,春花似錦互纯、人聲如沸瑟幕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽只盹。三九已至辣往,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間殖卑,已是汗流浹背站削。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留孵稽,地道東北人许起。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像菩鲜,于是被迫代替她去往敵國和親园细。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容