2014-05-16 62 views
1

我想搭上java.io.FileInputStream中的一個子類的超()與此類AspectJ中,無法攔截超()構造函數調用

package de.scrum_master.app; 

class ABC { 
    public ABC() { 
     System.out.println("Ctr ABC"); 
    } 
} 

public class DEF extends ABC { 
    public DEF() throws Exception { 
     System.out.println("Ctr DEF"); 
    } 

    static class MyFileInputStream extends java.io.FileInputStream { 
     MyFileInputStream() throws Exception { 
      super("de/scrum_master/app/ABC.java"); // HERE 
     } 
    }; 

    public static void main(String[] args) throws Exception { 
     new MyFileInputStream(); 
     new DEF(); 
    } 
} 

我能趕上DEF和ABC之間的初始化這樣:

@Before("initialization(de.scrum_master.app.DEF.new(..))") 
public void test(JoinPoint thisJoinPoint) throws AuditReactiveException { 
    System.err.println("Aspect DEF:"+thisJoinPoint); 
} 

但與java.io.FileInputStream中

@Before("initialization(java.io.FileInputStream.new(..))") 
    public void test2(JoinPoint thisJoinPoint) throws Exception { 
     System.err.println("Aspect FileInpputStream:"+thisJoinPoint); 
    } 

爲什麼?謝謝。

回答

3

簡單的問題,簡單的回答:因爲FileInputStream不是您自己的代碼庫的一部分,而是JDK/JRE的一部分。 JDK超越了AspectJ的影響力,因爲它的類是您的應用程序及其方面在其中執行的運行時的一部分。您可以捕獲對JDK類的調用,但不捕獲執行。也許你是

call(java.io.FileInputStream.new(..)) 

P.S:您還可以通過創建一個例如方面富集版編織方面對進入JRE類幸運rt.jar,但這既不推薦也不平凡。我已經完成了,只是爲了看看它是否有效。但採取這樣的措施通常是一個糟糕的方面設計的症狀,而不是一個真正的問題的解決方案。

更新:那麼,我忘記了call()切入點的語義。 AspectJ documentation說:

方法調用:調用方法時,不包括非靜態方法的超級調用。

因此,實際上,無需創建編織JDK/JRE不能捕捉super()呼叫或JDK/JRE的構造函數初始化。如果在建議中使用call()preinitialization()切入點,至少可以確保在超級構造函數中出現可能的異常之前發生了日誌記錄 - initialization()在超級構造函數被調用後發生。

更新2:請參閱this discussion如果你想知道爲什麼這不起作用的技術細節。注意,這實際上並不適用於AspectJ新手,我只是將它作爲任何其他人陷入這個問題的參考。