aop 获取注解注释的方法

有时,我想记录(通过slf4j和log4j )方法的每次执行,查看其接收的参数,返回的内容以及每次执行花费的时间。 这是我在AspectJ , jcabi-aspects和Java 6注释的帮助下所做的事情:

public class Foo {@Loggablepublic int power(int x, int p) {return Math.pow(x, p);}
}

这是我在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有一个参数,在这种情况下,该参数表示在以下情况下建议应适用于方法:

  1. 其可见性修饰符为*publicprotectedprivate );
  2. 它的名字是名字* (任何名字);
  3. 它的参数是.. (任何参数); 和
  4. 它用@Loggable注释

如果要截获对带注释的方法的调用,则在执行实际方法之前,先执行方法around() 。 当要拦截对power()方法的调用时, around()方法将接收ProceedingJoinPoint类的实例,并且必须返回一个对象,该对象将作为power()方法的结果使用。

为了调用原始方法power() ,建议必须调用连接点对象的proceed()

我们编译此方面,并使其与主文件Foo.class一起在classpath中可用。 到目前为止,一切都很好,但是我们需要采取最后一步,以便将我们的方面付诸实践-我们应该应用我们的建议。

二元方面编织

方面编织是建议应用过程的名称。 Aspect Weaver通过注入对Aspect的调用来修改原始代码。 AspectJ正是这样做的。 我们给它提供了两个二进制Java类Foo.classMethodLogger.class ; 它给退三-修改Foo.classFoo$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方法记录相关推荐

  1. java native方法_并发系列-native函数回调Java方法原理实践

    写在前面 上一篇分享了Java调用native函数过程原理实践,文章最后留了一个问题,本章主要对C程序回调我们的Java程序原理进行实践. 调用C程序之后他是怎么知道来调用我们我们的哪个方法?又是如何 ...

  2. 如何获取注解中的值_如何在运行时利用注解信息

    注解( annontation )是 Java 1.5 之后引入的一个为程序添加元数据的功能.注解本身并不是魔法,只是在代码里添加了描述代码自身的信息,至于如何理解和使用这些信息,则需要专门的解析代码 ...

  3. 特征选择方法_识别最优的数据驱动特征选择方法以提高分类任务的可重复性

    请点击上面"思影科技"四个字,选择关注作者,思影科技专注于脑影像数据处理,涵盖(fMRI,结构像,DTI,ASL,EEG/ERP,FNIRS,眼动)等,希望专业的内容可以给关注者带 ...

  4. tp3 默认模块 默认方法_您需要了解的有关默认方法的所有信息

    tp3 默认模块 默认方法 因此,默认方法是--昨天的新闻,对不对? 是的,但是使用了一年之后,积累了很多事实,我想将这些事实收集在一个地方,供刚开始使用它们的开发人员使用. 甚至有经验的人都可以找到 ...

  5. c++怎么将两个类的方法集合成一个类的方法_一文帮你梳理 Java 集合

    集合在我们日常开发使用的次数数不胜数,ArrayList/LinkedList/HashMap/HashSet······信手拈来,抬手就拿来用,在 IDE 上龙飞凤舞,但是作为一名合格的优雅的程序猿 ...

  6. java 反射获取属性名和值_面试官这样问我Java反射原理,我刚好都会

    上周我投递出了简历,岗位是java后端开发工程师.这周美团面试官给我进行了面试,面试过程中他问了Java的反射原理.(不得不夸一句,美团的效率真高,上午面完一面,晚上二面马上安排上了.) 无论什么Ja ...

  7. java注释搞笑图案_搞笑的代码注释,那些有趣的程序员

    发表于 2019-04-24 16:11:26 by 月小升 搞笑 /*** * .::::. * .::::::::. * ::::::::::: F*CK YOU * ..:::::::::::' ...

  8. python中注释的快捷键_【Python】注释

    一.Python注释: 1.单行注释 python中单行注释采用 # 开头. #!/usr/bin/python # coding:utf-8 import os import sys import ...

  9. python中repr方法_(转)Python中的常见特殊方法—— repr方法

    在Python中有些方法名.属性名的前后都添加了双下划线,这种方法.属性通常都属于Python的特殊方法和特殊属性,开发者可以通过重写这些方法或者直接调用这些方法来实现特殊的功能.其实前面见过的构造方 ...

最新文章

  1. 10.5 Throwable类
  2. CRM客户主数据UI上有哪些字段可以触发partner determination
  3. spark 笔记 16: BlockManager
  4. leetcode 406. 根据身高重建队列(贪心算法)
  5. C++ public、protected、private 继承方式的区别
  6. Extjs介绍及视频教程
  7. python123高次方程求根_GitHub - loveunk/math-advanced-algebra-notes: 根据丘维声的《高等代数》整理...
  8. js word 预览_关于Word打印的2个秘密,90%的人都不知道
  9. QPainter绘图基本使用
  10. Shell脚本基础语法教程
  11. 小程序之模版消息通知
  12. Word-去掉标题前面的小黑点
  13. oeasy教您玩转vim - 43 - # 替换模式
  14. c#物联网_毕业季我与你招聘信息中移物联网
  15. 中国农业生物多样性危机-农业大健康·蒋高明:谋定生态安全
  16. 桃词典 Peach Dictionary 简易英语词典app开发 安卓软件开发 The End 导航页及收尾工作
  17. Android Poco初始化时,不大起眼但可能存在坑点的参数们
  18. java8中的Collectors.groupingBy用法
  19. 私有化云原生交付、8K 360VR直播……大厂技术专家揭秘金牌背后的“黑科技”...
  20. Xshell7如何查看登录密码

热门文章

  1. P1850-换教室【数学期望,dp,Floyd】
  2. P2947-[USACO09MAR]向右看齐Look Up【单调栈】
  3. 【树链剖分】LCA(P4211)
  4. 【暴力】I Liked Matrix!
  5. 动态规划训练25 [Food Delivery ZOJ - 3469 ]好题
  6. 2016陕西省ACM 热身体B 种类并查集
  7. JFreeChart(五)之XY图
  8. js深度复制一个对象使用JSON.stringify是最好的办法吗
  9. 如何实现省市关联的下拉列表
  10. sql server高级查询,看这篇文章就够了