2017-03-16 167 views
2

我讀過Spring AOP不能攔截私有和受保護的方法,但它是以一種奇怪的方式攔截它們爲什麼是這樣?爲什麼Spring AOP在某些情況下攔截受保護的方法?

我有這些功能,我想攔截:

public String getName(String string) { 
    System.out.println("Name : " + name + string); 
    return name; 
} 

protected String getNamesprotected(String string) { 
    System.out.println("Name : " + name + string); 
    return name; 
} 

這是我的@Aspect代碼:

@Aspect 
public class Logging { 

    @Before("execution(* com.tutorialspoint.Student.*Name*(..))") 
    public void beforeAdvice(JoinPoint joinPoint){ 
     System.out.println("Going to setup student profile."+joinPoint.getSignature().toString()); 
    } 
} 

當執行該代碼雙方的getName和getNamesprotected被截獲,但是當我執行該代碼:

@Aspect 
public class Logging { 

    @Before("execution(* com.tutorialspoint.Student.getNamesprotected(..))") 
    public void beforeAdvice1(JoinPoint joinPoint){ 
     System.out.println("Going to setup student profile."+joinPoint.getSignature().toString()); 
    } 
} 

然後沒有任何東西被攔截。我也嘗試用*getNamesprotected*替換getNamesprotected,但仍不攔截。它只在*Name*在那裏時截獲。

任何人都可以解釋爲什麼會發生這種情況嗎?

+2

除非您使用AspectJ而不是Spring AOP,否則您所描述的內容難以置信。我只是覺得你犯了一個錯誤。 Spring AOP永遠不會攔截受保護的方法。如果您仍然認爲它確實存在,請在GitHub上使用[SSCCE](http://sscce.org/)進行證明。然後,我願意看看。 – kriegaex

+0

你可以舉一個例子SSCCE。我是新來的,所以不知道如何創建一個。 –

+1

你是認真的嗎?你甚至可以關注鏈接並閱讀SSCCE的含義嗎?如果你仍然不明白它的含義以及如何用你自己的代碼創建一個代碼,那麼你要麼完全缺乏作爲軟件開發人員的天賦,而應該嘗試找到一份新工作或者你只是懶惰。我選擇給你懷疑的好處,並拒絕認爲你是一個糟糕的開發者。因此我認爲懶惰是你的問題。所以,請儘可能尊重您的想法,您是否打算開啓您的大腦並嘗試幫助其他人幫助您回答您的問題? – kriegaex

回答

6

因爲OP(Prateek古普塔)似乎無法(而不願意)創造一個再現問題的小問題,而我在茶歇期間只是無聊,我很快就用Spring Boot自己創建了一個,並且非常驚訝Spring AOP確實與文檔相沖突至少在某些情況下當涉及CGLIB代理時,立場與受保護方法匹配。

因此,我爲自己註冊了一個Spring的Jira問題跟蹤器,並將此迴歸報告爲SPR-15354。如果您對Spring開發團隊的答案感興趣,您可能希望訂閱該門票上的更新。


更新:回答我的票的人告訴我,這是一個文檔的問題。正如2006年的SPR-1611告訴我們的那樣,Spring 1.2.7的目的已經改變了,但是從來沒有找到它的方法。底線:受保護的方法可以通過Spring AOP捕獲,這不是偶然的,但是已經有12年沒有記錄。


更新2:更新的文檔的文本將在明年春季發佈。如果您今天想要閱讀固定文本,請參閱SPR-1611

+0

感謝您的回答。並澄清我並不懶惰,只是我對這個行業不熟悉,現在甚至沒有畢業。我之前沒有使用GitHub,也沒有使用過StackOverflow。這是我第一次在一個行業工作(實習一個月)。我確實閱讀了關於SSCCE的手冊,並瞭解它是什麼,但由於我不知道GitHub,所以我無法創建一個,這就是爲什麼我要求一個樣本,以便至少了解它是如何完成的。 –

+3

親愛的Prateek,對於這個行業或者StackOverflow來說,一個新的障礙是如何創建一個能夠再現您的問題的小型的,降低到最小的獨立示例?我看不到那個。對不起,如果你的代碼中有可重現的問題,你應該能夠從你的大項目中提取一個最小版本的小項目。你不需要畢業就可以做到這一點。能夠將你的代碼檢入Git倉庫是一項基本的開發技巧,如果沒有它,任何一個開發人員如何生存?你可以在一天中學習。 – kriegaex

+0

我剛剛更新了我的答案,並附有新票狀態和解釋。 – kriegaex

1

任何人都可以解釋爲什麼會發生這種情況嗎?

由於Spring的AOP框架的基於代理的性質,保護的方法是通過定義不攔截,既不是JDK代理(其中,這是不適用),也不是CGLIB代理(其中這在技術上是可行的,但不建議用於AOP目的)。

因此,任何給定的切入點將僅與公共方法匹配!

如果您的攔截需求包括protected/private方法或構造函數,請考慮使用Spring驅動的本機AspectJ編織,而不是Spring的基於代理的AOP框架。

當執行該代碼雙方的getName和getNamesprotected被截獲

@Before("execution(* com.tutorialspoint.Student.*Name*(..))") 

這裏前面的通配符匹配任何修飾的方法(公有,保護和私有)和任何返回類型。參數列表中的兩個點匹配任意數量的參數。

試試這個應該執行受保護的方法

@Pointcut("execution(protected * *.*(..))") 

你也可以試試這個它是否適合你(我不是100%確定)

@Before("execution(* com.tutorialspoint.Student+.getNamesprotected(..))") 
+3

雖然你所說的都是正確的,但它並不回答OP的原始問題。 – kriegaex

+0

「@Pointcut(」execution(protected * *。*(..))))和'@Before(「execution(* com.tutorialspoint.Student + .getNamesprotected(..))」)'都不能攔截在我的問題中,受保護的方法只有'* Name *'是攔截受保護的,因爲我使用的是Spring AOP,所以理想情況下不應該發生這種情況。 –

相關問題