aop 获取注解注释的方法_带有AOP和注释的Java方法记录
aop 獲取注解注釋的方法
 有時,我想記錄(通過slf4j和log4j )方法的每次執行,查看其接收的參數,返回的內容以及每次執行花費的時間。 這是我在AspectJ , jcabi-aspects和Java 6注釋的幫助下所做的事情: 
這是我在log4j輸出中看到的:
[INFO] com.example.Foo #power(2, 10): 1024 in 12μs [INFO] com.example.Foo #power(3, 3): 27 in 4μs很好,不是嗎? 現在,讓我們看看它是如何工作的。
帶有運行時保留的注釋
注釋是Java 6中引入的一種技術。它是一種元編程工具,它不會改變代碼的工作方式,但會為某些元素(方法,類或變量)提供標記。 換句話說,注釋只是附加到可以查看和閱讀的代碼的標記。 有些注釋僅在編譯時可見-編譯后在.class文件中不存在。 其他的在編譯后仍然可見,并且可以在運行時訪問。
例如, @Override是第一種類型(其保留類型是SOURCE ),而來自JUnit的@Test是第二種類型(保留類型是RUNTIME )。 @Loggable (我在上面的腳本中使用的那個)是jcabi-aspects中第二種類型的注釋。 編譯后,它與.class文件中的字節碼保持在一起。
同樣,重要的是要理解,即使對power()方法進行了注釋和編譯,它到目前為止也不會向slf4j發送任何內容。 它僅包含一個標記,上面寫著“請記錄我的執行情況”。
面向方面的編程(AOP)
AOP是一種有用的技術,它允許在不顯式更改源代碼的情況下將可執行塊添加到源代碼。 在我們的示例中,我們不想在類內部記錄方法的執行情況。 相反,我們希望其他類攔截對方法power()每次調用,測量其執行時間,然后將此信息發送給slf4j。
我們希望該攔截器理解我們的@Loggable批注并記錄對該特定方法power()每次調用。 而且,當然,相同的攔截器應用于將來我們將放置相同批注的其他方法。
這種情況完全符合AOP的初衷-避免在多個類中重新實現某些常見行為。
日志記錄是我們主要功能的補充功能,我們不想使用多個日志記錄指令來污染我們的代碼。 相反,我們希望在后臺進行日志記錄。
就AOP而言,我們的解決方案可以解釋為創建一個方面 ,該方面在某些連接點處橫切代碼,并應用環繞建議以實現所需的功能。
縱橫比
讓我們看看這些魔術詞的含義。 但是,首先,讓我們看一下jcabi-aspects如何使用AspectJ實現它們(這是一個簡化的示例,您可以在MethodLogger.java找到完整的代碼):
@Aspect public class MethodLogger {@Around("execution(* *(..)) && @annotation(Loggable)")public Object around(ProceedingJoinPoint point) {long start = System.currentTimeMillis();Object result = point.proceed();Logger.info("#%s(%s): %s in %[msec]s",MethodSignature.class.cast(point.getSignature()).getMethod().getName(),point.getArgs(),result,System.currentTimeMillis() - start);return result;} }這是一個方面 ,里面有一個關于 around() 建議 。 方面用@Aspect注釋,而建議用@Around注釋。 如上所述,這些注釋只是.class文件中的標記。 除了為那些對運行時感興趣的人提供一些元信息外,他們什么也不做。
注釋@Around有一個參數,在這種情況下,該參數表示在以下情況下建議應適用于方法:
如果要截獲對帶注釋的方法的調用,則在執行實際方法之前,先執行方法around() 。 當要攔截對power()方法的調用時, around()方法將接收ProceedingJoinPoint類的實例,并且必須返回一個對象,該對象將作為power()方法的結果使用。
為了調用原始方法power() ,建議必須調用連接點對象的proceed() 。
我們編譯此方面,并使其與主文件Foo.class一起在classpath中可用。 到目前為止,一切都很好,但是我們需要采取最后一步,以便將我們的方面付諸實踐-我們應該應用我們的建議。
二元方面編織
方面編織是建議應用過程的名稱。 Aspect Weaver通過注入對Aspect的調用來修改原始代碼。 AspectJ正是這樣做的。 我們給它提供了兩個二進制Java類Foo.class和MethodLogger.class ; 它給退三-修改Foo.class , Foo$AjcClosure1.class和未修改MethodLogger.class 。
為了了解哪些建議應應用于哪些方法,AspectJ weaver使用了.class文件中的注釋。 同樣,它使用反射來瀏覽類路徑上的所有類。 它通過@Around注釋分析哪些方法滿足條件。 當然,它找到我們的方法power() 。
因此,有兩個步驟。 首先,我們使用javac編譯.java文件,并獲得兩個文件。 然后,AspectJ編織/修改它們并創建自己的額外類。 編織后,我們的Foo類如下所示:
public class Foo {private final MethodLogger logger;@Loggablepublic int power(int x, int p) {return this.logger.around(point);}private int power_aroundBody(int x, int p) {return Math.pow(x, p);} }AspectJ weaver將我們的原始功能移至新方法power_aroundBody() ,并將所有power()調用重定向到方面類MethodLogger 。
現在,我們有四個類一起工作,而不是Foo類中的power()方法。 從現在開始,這就是每次調用power()幕后發生的事情:
方法power()原始功能由圖中的綠色小生命線指示。
如您所見,方面編織過程將類和方面連接在一起,并通過連接點在它們之間轉移調用。 無需編織,類和方面都只是帶有附加注釋的已編譯Java二進制文件。
jcabi方面
jcabi-aspects是一個JAR庫,其中包含Loggable注釋和MethodLogger方面(順便說一句,還有更多方面和注釋)。 您無需編寫自己的方面來記錄方法。 只需在類路徑中添加一些依賴項,然后配置jcabi-maven-plugin進行編織(在Maven Central中獲取其最新版本):
<project><depenencies><dependency><dependency><groupId>com.jcabi</groupId><artifactId>jcabi-aspects</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId></dependency></dependency></depenencies><build><plugins><plugin><groupId>com.jcabi</groupId><artifactId>jcabi-maven-plugin</artifactId><executions><execution><goals><goal>ajc</goal></goals></execution></executions></plugin></plugins></build> </project>由于此編織過程需要大量的配置工作,因此我創建了一個具有ajc目標的便捷Maven插件,該插件可以完成整個方面的編織工作。 您可以直接使用AspectJ,但是我建議您使用jcabi-maven-plugin 。
而已。 現在,您可以使用@com.jcabi.aspects.Loggable注釋,您的方法將通過slf4j記錄。
如果某些內容無法按照說明進行操作,請立即提交Github問題 。
相關文章
您可能還會發現以下有趣的帖子:
- 如何重試異常的Java方法調用
 - 緩存Java方法結果
 - 擺脫Java靜態記錄器
 - 限制Java方法執行時間
 - 簡單的Java SSH客戶端
 
翻譯自: https://www.javacodegeeks.com/2014/09/java-method-logging-with-aop-and-annotations.html
aop 獲取注解注釋的方法
總結
以上是生活随笔為你收集整理的aop 获取注解注释的方法_带有AOP和注释的Java方法记录的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 原生安卓锁屏下载(原生安卓锁屏)
 - 下一篇: 定义ddl(定义ddos)