利用AspectJ + Gradle 来实现非 Spring 下的 AOP 注解

news/2024/5/20 5:26:01 标签: gradle, aop, annotations

有些时候我们有一个需求,就是能够统计增加了某个注解方法的执行时间。很自然的,我们能够想到用AOP的方法。
由于我们熟悉编写的代码是在 Spring 下面的编写的 AOP 注解,但是很多时候,我们可能并不一定需要去一个庞大的Spring 环境,才能够实现 AOP 的功能。因为我仅仅想做的就是一个在多线程下的方法性能测试,我只是想启动最少量的代码,来实现我需要的切面功能。

搜索了一番之后终于找到在 Gradle 项目中,不启动 Spring 环境,来使用 AOP 的方案。

下面的代码将实现以@ExecutionTime 注解来修饰方法,获得方法的统计时间。

Gradle的配置

目前暂时没有找到一个官方支持的AspectJ Gradle 插件。如果你用的是 Gradle5 以上的版本,建议你跟我一样使用 arendd/AspectjGradlePlugin: AspectJ Plugin for Gradle 5+ 插件。

project.ext {
    aspectjVersion = '1.9.7'
}

buildscript {
    repositories {
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath "gradle.plugin.de:AspectjGradlePlugin:0.0.6"
    }
}

apply plugin: "aspectj.AspectjGradlePlugin"
group 'top.ilovestudy.tools'
version 'unspecified'

dependencies {
    implementation "org.aspectj:aspectjrt:${aspectjVersion}"
    implementation "org.aspectj:aspectjweaver:${aspectjVersion}"
    implementation "org.aspectj:aspectjtools:${aspectjVersion}"
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
java {
    sourceCompatibility JavaVersion.VERSION_11
    targetCompatibility JavaVersion.VERSION_11
}
test {
    useJUnitPlatform()
}

增加一个 ExecutionTime 注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExecutionTime {
    ChronoUnit unit() default ChronoUnit.NANOS;
}


增加一个 aspect 实现类 ExecutionTimeAspect

@Aspect
public class ExecutionTimeAspect {

    @Pointcut("@annotation(executionTime)")
    public void callAt(ExecutionTime executionTime) {
    }


    @Around("callAt(executionTime)")
    public Object around(ProceedingJoinPoint pjp, ExecutionTime executionTime) throws Throwable {
        long start = System.nanoTime();
        Object proceed = pjp.proceed();
        long end = System.nanoTime();
        System.out.println(String.format("[%s] method [%s] execution time: %s %s",
                Thread.currentThread().getName(),
                pjp.getSignature().getName(),
                Duration.of(end - start, ChronoUnit.NANOS).get(executionTime.unit()),
                executionTime.unit().name()));
        return proceed;
    }

}

使用

    @ExecutionTime
    void add10K() {
        int idx = 0;
        while (idx++ < maxCountNum) {
            addOne();
        }
    }

然后,不管我们在 Junit5 测试框架中,还是实现的代码中,调用 add10K 的方法,都会获得一个日志的记录(线程,方法,执行时间),表示运行 add10K 耗费了多少时间。例如:

[calc7] method [add10K] execution time: 3841505 NANOS
[calc0] method [add10K] execution time: 48612486 NANOS
[calc1] method [add10K] execution time: 53342401 NANOS
[calc3] method [add10K] execution time: 55629095 NANOS
[calc5] method [add10K] execution time: 56005109 NANOS
[calc7] method [add10K] execution time: 56238950 NANOS

参考文档

  1. arendd/AspectjGradlePlugin: AspectJ Plugin for Gradle 5+
  2. Javing: AspectJ + Custom Annotation + Gradle (Without Spring)

http://www.niftyadmin.cn/n/1183209.html

相关文章

《开源SOA》译者序

相信大家对SOA这个词并不陌生&#xff0c;很多企业都在讲我们要上SOA&#xff0c;也有很多企业在呼应&#xff1a;我们能帮忙。但究竟什么是SOA&#xff0c;SOA能做什么&#xff0c;如何在企业中推行SOA&#xff0c;采用什么样的技术&#xff0c;这些都是摆在我们面前的现实问题…

Java8 中的函数式接口

函数式编程是一种思想&#xff0c;也是一种编程理念。知乎上有个答主我觉得回答的 很好&#xff0c;不了解的可以看看。什么是函数式编程思维&#xff1f; - 知乎 我们更关注于数据的映射。也就是我们数据中&#xff0c;怎么从 A 到 B 的这部分逻辑。 FunctionalInterface注解…

JavaSE学习 第十八章 JDBC编程[详解]

1.数据库简介 数据库&#xff08;DB&#xff0c;Data Base &#xff09; 数据库管理系统&#xff08;DBMS&#xff0c;Data Base Management System&#xff09; 关系型数据库&#xff08;RDB&#xff09; 关系型数据库管理系统&#xff08;RDBMS&#xff09; SQL语言&#xff…

531KF在线客服系统,欢迎拍砖,免费下载!!!【原创】

某个客户看中了某个在线客服系统&#xff1b;要做个和他一样的&#xff1b;于是就从宇宙中空降了一个531KF&#xff1b; 531KF(ASP.NET(C#) AJAX)在线客服系统V1.0.1222 演示版demo.html 为演示文件;531KF在线客服系统免费使用;免费版中 除系统管理员外,其它客服无法修改密码…

如何给你的 Git 提交进行签名

最近计划给一个开源软件&#xff0c;做一些英译中的翻译&#xff0c;看了他的 Readme 之后&#xff0c;发现他们需要贡献者的提交是被 verify 的。也就是说你的每次 git commit 都是被自己签名过的提交它们才会接受&#xff0c;在这个需求下&#xff0c;因此看下了&#xff0c;…

分页工具类

public class PageSupport {public final static int PAGE_SIZE 5;//当前页码-来自于用户输入private int currentPageNo 1;//总记录数private int totalCount 0;//页面容量private int pageSize 0;//总页数-totalCount/pageSize&#xff08;1&#xff09;private int tota…

学用 ASP.Net 之 字符串 (3): string 类的非扩展方法

string 类的非扩展成员:/* 类方法 */ string.Compare; //对比, 返回 1、0 或 -1 string.CompareOrdinal; //对比, 返回序号差 string.Concat; //合并 string.Copy; //复制 string.Equals; //是否同值 string.Format; …

07Vue-router路由

目录 1. main.js 【演示导入组件】 2.App.vue [演示使用] 3.1Content.vue 4.index.js 5.main.js 【配置路由】 6.使用App.vue 安装 基于第一个vue-cli进行测试学习&#xff1b; 先查看node modules中是否存在vue-router    vue-router是一个插件包&#xff0c; 所以…