V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ychost
V2EX  ›  Java

FastAop,一款基于 Java 编译时的 Aop 框架

  •  
  •   ychost · 2021-03-29 10:15:11 +08:00 · 3269 次点击
    这是一个创建于 1095 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目地址

    https://github.com/fast-light/fastaop

    项目刚上线,后面会持续维护,Maven 中央仓库还在申请中

    项目简介

    FastAop 是一款基于 Java Annotation Processing 的 AOP 框架,其原理和 Lombok 类似,通过对编译过程的拦截,修改方法的语法树并织入切面代码从而实现了 AOP 的功能,相较于传统的 AspectJ 、Spring-AOP 框架有如下特点:

    1. 依赖干净,无需 Spring 等环境
    2. 使用简单,仅需两个注解就能实现切面功能
    3. 性能好,由于是编译过程中植入原生代码,所以性能几乎无损
    4. 功能强大,支持 private 、static 等各种方法切面,内部方法相互调用也会过切面逻辑
    5. 扩展性好,提供了特定注解,能够在方法内部拿到当前切面上下文,便于做一些临时操作

    项目由来

    在写一些二方库的时候,有时候会有 aop 需求,但是又不想引入 AspectJ 或者 Spring 这种重量级的框架,那么 FastAop 就是你的另一个选择,原理和 Lombok 一样在编译的时候修改语法树注入的切面代码,目前已用在了生产环境,当然可以基于这个库可以生成任何你想要的模板代码,欢迎大家一起交流~

    29 条回复    2021-12-15 18:30:28 +08:00
    blindpirate
        1
    blindpirate  
       2021-03-29 10:23:41 +08:00
    所以它也像 lombok 一样违反了 annotation processor 的规定,在 annotation processing 的过程中使用了 javac 的私有 API,修改了生成的文件?
    dbpe
        2
    dbpe  
       2021-03-29 10:27:47 +08:00
    同 1L 的疑问...
    ychost
        3
    ychost  
    OP
       2021-03-29 10:37:45 +08:00
    @blindpirate 是的,调用了 javac 的 api 去织入了切面代码,传统的 Aop 在运行时也会改 class 文件
    ychost
        4
    ychost  
    OP
       2021-03-29 10:40:14 +08:00
    @dbpe 是的,编译的时候魔改了语法树
    dqzcwxb
        5
    dqzcwxb  
       2021-03-29 10:40:15 +08:00
    cglib?
    ychost
        6
    ychost  
    OP
       2021-03-29 10:42:34 +08:00
    @dqzcwxb 不是,用的 Java 自带的 Annotation Processor 技术
    bthulu
        7
    bthulu  
       2021-03-29 10:51:43 +08:00
    最烦这种在编译过程中干黑活的, 能不用还是不要用了
    ychost
        8
    ychost  
    OP
       2021-03-29 10:59:06 +08:00
    @bthulu 编译干活和运行时干活本质差不多,都是魔改,受限于 Java 语法限制只能通过注解处理来搞定,如果有 C#/Kotlin 那么灵活就不会出现 Lombok 这样的框架了
    JinTianYi456
        9
    JinTianYi456  
       2021-03-29 11:05:14 +08:00
    @blindpirate 想了解下 "lombok 一样违反了 annotation processor 的规定",弱弱问下,是违反了什么规定?
    chendy
        10
    chendy  
       2021-03-29 11:09:19 +08:00
    star 了,之前玩过代码生成,这次看看到底怎么黑 javac
    zhao1014
        11
    zhao1014  
       2021-03-29 11:09:51 +08:00 via Android
    同不了解 annotation processor 规定是什么,有老哥大致解释一下吗?
    lewis89
        12
    lewis89  
       2021-03-29 11:11:20 +08:00   ❤️ 1
    @bthulu 能做到透明,其实还好,看能不能支持 aspectJ 的 切点语法 以及环绕监听...
    其实.. 说白了 还是上 SpringBoot 吧.. 现在这些框架 AOP 以及各种组件 都做的非常好了,搞 Java 的根本不在乎轻量化这个东西,关键是思维负担上的轻量化,至于本身生成的代码尺寸,我觉得都不是什么大事..
    ychost
        13
    ychost  
    OP
       2021-03-29 11:27:02 +08:00
    @lewis89 这个项目的初衷主要是为了解决两个东西,1. Aop 性能问题(实测) 2. 二方库用 Aop,二方库依赖过重会导致排包困难,版本冲突等问题
    ychost
        14
    ychost  
    OP
       2021-03-29 11:28:03 +08:00
    @ychost 实测性能是高于 Cglib 和 JDK 动态代理,这几个性能都很高性能损失在 0.3% 左右,FastAop 性能损失在 0.1%
    blindpirate
        15
    blindpirate  
       2021-03-29 11:40:41 +08:00
    @JinTianYi456
    @zhao1014

    Java 的 AP spec 只允许在 AP 的时候生成新文件,不允许修改已有的编译输出,i.e. compiled class 。lombok 违反了这个规定,且有传染性(一个人用就逼迫所有人都要安装插件),因此我个人不喜欢用 lombok 。

    > The "hack" in Lombok is that, strictly speaking, the annotation processing spec doesn't allow you to modify existing classes. The annotation processing API doesn't provide a mechanism for changing the AST of a class. The clever people at Project Lombok got around this through some unpublished APIs of javac.

    另,“修改编译输出的 class 文件”和“AOP 在运行时修改载入 JVM 的 Class 对象”是两个概念,前者属于 AST 变换,后者属于 bytecode manipulation
    Betsy
        16
    Betsy  
       2021-03-29 12:08:31 +08:00 via iPhone
    没有单元测试,这看着有点慌哈。
    我试了下,windows 系统 mvn clean package 也打不出来包,会报错
    ychost
        17
    ychost  
    OP
       2021-03-29 12:31:59 +08:00
    @Betsy 项目刚上线,还没来得及补测试用例,windows 系统的问题,我晚上装个虚拟机看看,我在 mac 下面测 JDK8 没问题的
    uselessVisitor
        18
    uselessVisitor  
       2021-03-29 13:02:22 +08:00
    运行 install.sh 后,在新的 maven 项目中还是无法引入。。奇怪了,明明在本地仓库中看到了
    uselessVisitor
        19
    uselessVisitor  
       2021-03-29 13:17:20 +08:00
    @ychost 编译空指针咋回事
    ychost
        20
    ychost  
    OP
       2021-03-29 13:33:00 +08:00
    @beichenhpy 提个 issue 我看看
    cubecube
        21
    cubecube  
       2021-03-30 00:59:46 +08:00
    有 benchmark 么?运行时,已预热的的 benchmark 。
    VHacker1989
        22
    VHacker1989  
       2021-03-30 07:52:47 +08:00
    早就有人做过了,比如 micronaut,把 aop,ioc 都做到了编译时,还支持 graalvm native build 。
    LessonOne
        23
    LessonOne  
       2021-03-30 09:26:52 +08:00
    @ychost 应该没人会在意 这 0.2%的差距吧???
    ychost
        24
    ychost  
    OP
       2021-03-30 10:30:39 +08:00
    @cubecube
    @LessonOne
    性能差异可以忽略,主要目的是可以自己生成模板代码,不光是 aop,其它你想要的都能生成
    ychost
        25
    ychost  
    OP
       2021-03-30 10:35:54 +08:00
    @VHacker1989 micronaut 这个很优秀,但是它这个是对标 Spring 这种生态级别的,目的不一样,我这个只是个小工具
    ychost
        26
    ychost  
    OP
       2021-04-01 15:12:08 +08:00
    稍微翻了下 micronaut aop 的源码,它那个是通过继承替换 Bean 实现切面的,所以不能切内部方法、静态方法,好处是生成的一抹多文件,没有改源文件,生成的代码都是继承于源文件
    ychost
        27
    ychost  
    OP
       2021-04-01 15:12:21 +08:00
    @LessonOne 稍微翻了下 micronaut aop 的源码,它那个是通过继承替换 Bean 实现切面的,所以不能切内部方法、静态方法,好处是生成的一抹多文件,没有改源文件,生成的代码都是继承于源文件
    dk7952638
        28
    dk7952638  
       2021-12-15 08:03:12 +08:00
    我觉得可以参照 dagger 的思路通过 annotation porcessor 来实现接口,在接口里生成 aop 过程比较好一些,lombok 的方式一不是规范,二兼容性和移植性太差
    ychost
        29
    ychost  
    OP
       2021-12-15 18:30:28 +08:00
    @dk7952638 谢谢,我看过 micronaut 的源码,写的很好,不过很重,我就想轻一点,不想做个 framework
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   953 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 21:39 · PVG 05:39 · LAX 14:39 · JFK 17:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.