一個可能的解決方案是使用AspectJ。 AspectJ可以讓你定義你想要攔截的東西(所謂的連接點)並在發生時執行你想要的代碼(所謂的建議)。
連接點可以是一切,但在你的情況下,你需要用給定的註釋來捕獲方法的執行,所以我們將只使用「執行」連接點。
AspectJ然後需要檢測你的類。這是可以做到:
- 編譯代碼與AspectJ編譯器,它擴展了Java編譯器有什麼需要
- 「織」現有的jar文件,這樣你就可以正常的構建過程之後做到這一點,或者你甚至可以在沒有源文件的jar文件中執行它(這種情況並非如此,因爲無論如何您都需要放置註釋)。
我們將使用第一種方法只編譯方面,第二種方法來測試你想要的jar文件或類文件夾。
要做到這一點,您需要編寫一個必須具有運行時保留的註釋,可審覈的。
然後你寫一個方面:
public aspect Audit { // An aspect then compiles as if it was a class (at runtime, it is a normal class)
Object around() : // This is an around advice
execution(@Auditable * *(..)) // Here you're catching execution of any method of any class with any parameter and any return type, which is annotated with @Auditable
{
// Do what you want to do before the method
long start = System.nanoTime();
Logger.log("I'm entering into " + thisJoinPoint); // with thisJoinPoint you can extract a lot of informations, like what class, what method, what parameters, on which instance etc..
try {
Object ret = proceed(); // "proceed" goes on executing the method
// You could log, or do whatever you want with the return value, which could be "Void".
return ret;
} finally {
Logger.log("It took ns: " + (System.nanoTime() - start));
}
}
}
一旦你寫了這方面(通常在一個包,並以「.aj」擴展,但不是強制性的),你用AspectJ編譯器編譯。
ajc -outxml -classpath thisLib.jar:thatLib.jar -1.5 -outjar auditableAspect.jar package/of/your/AuditableAspect.aj
這與使用javac編譯java代碼很相似。在類路徑上,你需要編譯方面所需的東西,在這個例子中,我使用了一個神祕的Logger,它必須位於thisLis.jar或thatLib.jar中。
最後,您將擁有一個auditableAspect.jar文件,該文件將包含您方面的已編譯類。
現在,要使用它,您需要「編織」您希望它「截取」的類(或jar文件)。要做到這一點,仍然與濃縮蘋果汁命令:
ajc -inpath myStuff.jar -outjar myStuffAudited.jar -aspectPath auditableAspect.jar
然後,您會在的MyStuff myStuffAudited.jar相同的類找到。jar和其他一些合成的內部匿名類。
現在基本上你可以從你的應用程序類路徑(或WEB-INF/lib,如果它是一個web應用程序)中移除myStuff.jar,用myStuffAudited.jar替換它,並且添加auditableAspect.jar,這是你的aspect和aspectjrt .jar這是AspectJ運行時。
重新加載你的應用程序,它將開始記錄。
您可以在所有需要的罐子上或在for循環中的所有罐子上做到這一點;那些未受影響的將不受影響。
這可以在您的構建週期中以多種方式進行集成。
- 顯然,.BAT或.sh腳本可以自動執行它
- Ant有任務的AspectJ
- Maven有更多瞭解AspectJ插件
- Eclipse有編制和IDE
內編織一個插件
不知道你是如何建立你的項目,所以YMMV。
這是侵入與否,這是一個意見;但據我所知,沒有太多的軟件包提供運行時審計,而不用某種方式操縱類字節碼,如果不使用有限的(如你所見)接口的運行時代理。
還有一個選項可以使用編織類加載器,這將完全消除編織現有的jar和類的需要,因爲它們會在加載時由類加載器本身編織。它工作得很好,我喜歡它,但它取決於您的運行時環境。
AspectJ,但取決於你對「非侵入性」的解釋 – 2014-09-06 00:10:31
嗯,這很像「將註釋放在方法中並忘記它」。對於遺留應用程序,我不確定AspecJ會發生什麼情況。 – EdwinF 2014-09-10 16:20:31
即使您沒有源文件,AspectJ也可以處理遺留應用程序。 – 2014-09-10 18:01:40