我在 Kotlin-Gradle 多模块项目中使用
io.freefair.aspectj.post-compile-weaving
插件来启用我的 springboot 应用程序中的各个方面。
当我尝试在一个简单的项目中使用该插件时,它工作得非常好,然后当我将项目拆分为多模块时,它开始不再识别各个方面了
这是我在 github 上创建的 MCVE。
所以我基本上设置了根项目 gradle 文件:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.1.5"
id("io.spring.dependency-management") version "1.1.3"
id("io.freefair.aspectj.post-compile-weaving") version "6.6.3"
kotlin("jvm") version "1.8.22"
kotlin("plugin.spring") version "1.8.22"
}
group = "com.voiddev"
allprojects {
apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "kotlin-spring")
apply(plugin = "io.spring.dependency-management")
apply(plugin = "org.springframework.boot")
apply(plugin = "io.freefair.aspectj.post-compile-weaving")
version = "0.0.1-SNAPSHOT"
java {
sourceCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
testImplementation("org.springframework.boot:spring-boot-starter-test")
implementation("org.aspectj:aspectjrt:1.9.19")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
}
然后我所做的就是尝试使用“服务器”模块中“公共”模块中定义的方面。 我确实导入了服务器模块中的通用模块,因为我能够访问
common
模块中定义的类。
这是我的服务器 gradle 文件:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.1.5"
id("io.spring.dependency-management") version "1.1.3"
id("io.freefair.aspectj.post-compile-weaving") version "6.6.3"
kotlin("jvm") version "1.8.22"
kotlin("plugin.spring") version "1.8.22"
}
group = "com.voiddev"
dependencies {
implementation(project(":common"))
}
tasks {
bootJar {
archiveBaseName.set(rootProject.name)
}
}
然而这些方面却被忽视了
实际上,我想知道为什么你要使用原生 AspectJ,因为你将切面应用于 Spring 服务。即,常规的“AOP lite”,称为 Spring AOP,它随 Spring 一起提供,就足够了。为此,您不需要任何额外的构建插件。
无论如何,回答你的问题:你的模块
common
是一个方面库。为了使 AspectJ 编译器能够识别它,您应该将它放在切面路径上,而不是放在常规类路径上。在 Freefair 中,如此处记录,这样做是这样的:
dependencies {
aspect(project(":common"))
}
然后,就可以了。鉴于此服务器应用程序,...
@SpringBootApplication
class ServerApplication
fun main(args: Array<String>) {
runApplication<ServerApplication>(*args).use {
println(it.getBean(AspectService::class.java).randomFunction())
}
}
...控制台日志将是:
MetricAspect: $Proxy57
MetricAspect: $Proxy57
Hello Aspect
但是当然,使用本机 AspectJ 时您的切入点太通用了。它将匹配两次,一次匹配
call
,一次匹配 execution
连接点。在 Spring AOP 中不会发生这种情况,因为后者只知道execution
。你可以像这样修复它:
@After("@annotation(metricAnnotation) && execution(* *(..))")
控制台日志更改为:
MetricAspect: $Proxy57
Hello Aspect
您可能还想考虑将两个模块中的 Freefair 插件从 6.6.3 升级到 8.4:
id("io.freefair.aspectj.post-compile-weaving") version "8.4"