Spring AOP造成的@Controller注冊失敗

昨天在重構(gòu)項目時 ,抽取了Controller的公共方法到AbstractController中, 調(diào)整了原有Controller的路徑 (包名) . 然后啟動時發(fā)現(xiàn)幾乎所有移動過包的Controller都失效了.

主要對象

  • ControllerLogInterceptor : aop攔截器 ,攔截目標(biāo)路徑下所有Controller
@Pointcut("execution(public * com.eddy..*.*Controller.*(..))")
public void handleController() {
}
  • AppController : 一個接口
public interface AppController {
    String getAppName();
}
  • AbstractController : 抽象的Controller ,包含一些公用方法 ;實現(xiàn)了AppController接口
@Slf4j
public abstract class AbstractController implements AppController {
    @Autowired
    protected HttpSession session;

    @Override
    public String getAppName() {
        return OSC_APPNAME;
    }
}
  • ContactController : 業(yè)務(wù)邏輯的Controller
@RestController
@RequestMapping("/eddy/contact")
public class ContactController extends AbstractOSCController {
...
}

原因分析

  • 因為是移動路徑過后出現(xiàn)的 ,首先考慮路徑影響
    • 使用的SpringBoot ,全注解配置的Controller ,路徑并不會影響B(tài)ean的解析
    • 同路徑下某一Controller可用 ,該Controller沒有繼承AbstractController ,繼承了另一個類
  • 考慮AbstractController的影響
    • 改變路徑前也是使用繼承Controller的做法 ,沒有出現(xiàn)問題
    • 這個類也在AOP的匹配范圍內(nèi)
  • 修改了AbstractController->AbstractAction ,依舊無效
    • AOP主要是代理原有Bean ,Abstract不會生成Spring Bean ,不會產(chǎn)生作用
  • 終極大招 ,源碼斷點:
    • 打印Debug Log : ContactController注冊為Bean ,但沒有掃描到mapping路徑
    • 斷點查看Spring如何掃描Controller并添加mapping的

RequestMapping

通過日志 ,找到掃描Mapping的目標(biāo)類RequestMappingHandlerMapping (父對象AbstractHandlerMethodMapping#initHandlerMethods方法)

//AbstractHandlerMethodMapping.class
protected void initHandlerMethods() {
        if (logger.isDebugEnabled()) {
            logger.debug("Looking for request mappings in application context: " + getApplicationContext());
        }
        String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
                BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
                getApplicationContext().getBeanNamesForType(Object.class));

        for (String beanName : beanNames) {
            if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
                Class<?> beanType = null;
                try {
                    beanType = getApplicationContext().getType(beanName);
                }
                catch (Throwable ex) {
                    // An unresolvable bean type, probably from a lazy bean - let's ignore it.
                    if (logger.isDebugEnabled()) {
                        logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
                    }
                }
                if (beanType != null && isHandler(beanType)) {
                    detectHandlerMethods(beanName);
                }
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }

可以看到 ,通過循環(huán)已加載的Bean ,然后通過相應(yīng)Handler (這里是RequestMappingHandler) 判斷是否應(yīng)該處理.

//RequestMappingHandlerMapping.class
@Override
protected boolean isHandler(Class<?> beanType) {
    //判斷對應(yīng)class類是否 有Controller注解或繼承自Controller注解 (RestController) 
        return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
                AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
    }

這里斷點調(diào)試后 ,發(fā)現(xiàn)ContactController直接跳過 ,它沒有@Controller注解!!!! 但代碼里確實進行了配置 ,在經(jīng)過多次重編譯過后 ... 發(fā)現(xiàn)ContactController對應(yīng)Bean的classType是 com.sun.Proxy...

也就是說SpringAOP代理將這個Bean本有的信息抹除了 ,所以我修改了SpringAOP的匹配路徑 ,果然Controller可用了.

但是AOP部分的代碼也很重要 ,我不希望丟掉.同時我發(fā)現(xiàn)

  • 單一的Controller(無繼承關(guān)系) 和 AOP 工作的很好
  • 繼承自其他類的Controller也工作的很好
    那么 ,Spring的AOP應(yīng)該是不會破壞Bean的類型判斷的 : 他們的類型都是 com.eddy.ContactController$Spring..Cglib...這樣的 ,是能夠通過SpringMVC的檢查的

結(jié)論

最后的不同就在于那個簡單的接口...

  • Spring默認使用JDK ,對接口進行動態(tài)代理 : ContactController extends AbstractController implement AppController ,所以將與接口有關(guān)的類都代理成了Proxy .
  • 而繼承自單一類/沒有接口的 ,使用cglib代理 ,就不存在這個問題 ,他依舊保留了原有class的信息.

增加配置 spring.aop.proxy-target-class=true ,默認統(tǒng)一使用cglib即可

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子驱闷,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粹排,死亡現(xiàn)場離奇詭異,居然都是意外死亡涩澡,警方通過查閱死者的電腦和手機顽耳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妙同,“玉大人射富,你說我怎么就攤上這事≈嘀悖” “怎么了胰耗?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長芒涡。 經(jīng)常有香客問我柴灯,道長,這世上最難降的妖魔是什么拖陆? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任弛槐,我火速辦了婚禮,結(jié)果婚禮上依啰,老公的妹妹穿的比我還像新娘乎串。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布叹誉。 她就那樣靜靜地躺著鸯两,像睡著了一般。 火紅的嫁衣襯著肌膚如雪长豁。 梳的紋絲不亂的頭發(fā)上钧唐,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機與錄音匠襟,去河邊找鬼钝侠。 笑死,一個胖子當(dāng)著我的面吹牛酸舍,可吹牛的內(nèi)容都是我干的帅韧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼啃勉,長吁一口氣:“原來是場噩夢啊……” “哼忽舟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起淮阐,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤叮阅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后泣特,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體浩姥,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年群扶,在試婚紗的時候發(fā)現(xiàn)自己被綠了及刻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡竞阐,死狀恐怖缴饭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情骆莹,我是刑警寧澤颗搂,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站幕垦,受9級特大地震影響丢氢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜先改,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一疚察、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仇奶,春花似錦貌嫡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽别惦。三九已至,卻和暖如春夫椭,著一層夾襖步出監(jiān)牢的瞬間掸掸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工蹭秋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扰付,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓感凤,卻偏偏與公主長得像悯周,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子陪竿,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,955評論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)屠橄,斷路器族跛,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 什么是Spring Spring是一個開源的Java EE開發(fā)框架。Spring框架的核心功能可以應(yīng)用在任何Jav...
    jemmm閱讀 16,464評論 1 133
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,815評論 6 342
  • 文章作者:Tyan博客:noahsnail.com 3.5 Bean scopes When you create...
    SnailTyan閱讀 1,890評論 0 1
  • 第一章 畢業(yè)了 A市 某高校又迎來了讓人悲喜交加的畢業(yè)季。 “你們選好學(xué)校沒溪北?不知道是哪所學(xué)校這...
    路人有意閱讀 182評論 0 2