如何在Bazel构建的多模块Java/Scala仓库中使用AOP
Bazel多模块AspectJ编译时织入实现方案
核心思路
在Bazel中实现和Gradle一致的AspectJ编译时织入,需基于AspectJ的ajc编译器,分别处理Java(project-a)和Scala(project-b)模块的编译流程,复用project-c中的切面代码,同时利用Bazel增量编译特性保证性能。
WORKSPACE依赖配置
在项目根目录的WORKSPACE文件中引入AspectJ依赖:
load("@bazel_tools//tools/build_defs/repo:maven.bzl", "maven_install") maven_install( artifacts = [ "org.aspectj:aspectjrt:1.9.6", "org.aspectj:aspectjtools:1.9.6", ], repositories = [ "https://repo1.maven.org/maven2/", ], )
各模块BUILD文件示例
project-c(切面模块)
此模块仅编译切面Java代码,无需织入,作为普通Java库供其他模块依赖:
java_library( name = "project-c", srcs = glob(["src/main/java/**/*.java"]), deps = [ "@maven//:org_aspectj_aspectjrt", ], exports = [ "@maven//:org_aspectj_aspectjrt", ], visibility = ["//visibility:public"], ) filegroup( name = "srcs", srcs = glob(["src/main/java/**/*.java"]), visibility = ["//visibility:public"], )
project-a(Java模块)
直接使用ajc替代默认javac编译器,在编译时引入project-c的切面源码完成织入:
java_library( name = "project-a", srcs = glob(["src/main/java/**/*.java"]), deps = [ "//project-c:project-c", # 项目其他第三方依赖 ], # 指定AspectJ的ajc作为编译器 javac = "@maven//:org_aspectj_aspectjtools//jar", javacopts = [ # 引入切面源码路径,对应Gradle中的-sourceroots配置 "-sourceroots", "$(location //project-c:srcs)", "-Xlint:ignore", "-showWeaveInfo", # 可选,用于查看织入日志 ], )
project-b(Scala模块)
Scala需先编译为字节码,再通过ajc进行织入,保证Scala代码编译逻辑不受影响:
load("@io_bazel_rules_scala//scala:scala.bzl", "scala_library") # 第一步:编译Scala源码为未织入的字节码 scala_library( name = "project-b-unweaved", srcs = glob(["src/main/scala/**/*.scala"]), deps = [ "//project-c:project-c", # 项目其他Scala/Java依赖 ], ) # 第二步:用ajc对编译后的字节码进行切面织入 java_library( name = "project-b", srcs = [":project-b-unweaved"], deps = [ "//project-c:project-c", "@maven//:org_aspectj_aspectjrt", ], javac = "@maven//:org_aspectj_aspectjtools//jar", javacopts = [ "-inpath", "$(location :project-b-unweaved)", "-sourceroots", "$(location //project-c:srcs)", "-Xlint:ignore", ], )
性能优化注意事项
- 复用project-c的编译结果:通过Bazel的依赖机制,切面代码仅在修改时重新编译
- 增量编译:Bazel会自动追踪源码和依赖变化,仅重新编译受影响的模块
- 精准织入:通过
-sourceroots限定切面范围,避免不必要的字节码处理
关于Bazel Aspects文档的说明
你查阅的Bazel Aspects是用于构建流程扩展的特性,主要用于修改或增强Bazel的构建规则行为,和代码层面的AOP织入不属于同一范畴,因此不适用当前场景。
内容的提问来源于stack exchange,提问作者Ruchir Jain
相关产品推荐
相关产品推荐

