使用 AspectJ 和 Scala 时出错
Error when working with AspectJ and Scala
我正尝试在 IntelliJ 上使用 Scala 和 AspectJ 作为 IDE。 #文件结构
Sample.scala - (主要方法组成的class)
package sample
class SampleClass {
def printSample():Unit = println("hello")
}
object SampleObject extends App {
val sample = new SampleClass
sample.printSample()
}
Tracer.scala -(Tracer 功能或换句话说方面)
package sample
import org.aspectj.lang.annotation._
@Aspect
class Tracer {
@Before("execution(* sample.SampleClass.printSample(..))")
def printSample() {
println("Printing sample:")
}
}
build.sbt - 为了 运行 sbt 命令(sbt 编译和 sbt 运行)
name := "testingAspectScalaFullexample"
version := "0.1"
scalaVersion := "2.13.5"
lazy val buildSettings = Seq(
organization := "com.lightbend.sbt.aspectj",
version := "0.1-SNAPSHOT",
scalaVersion := "2.12.1"
)
lazy val sample = (project in file("."))
.settings(buildSettings)
.aggregate(tracer, instrumented)
// precompiled aspects
lazy val tracer = (project in file("tracer"))
.enablePlugins(SbtAspectj)
.settings(buildSettings)
.settings(
// input compiled scala classes
aspectjInputs in Aspectj += (aspectjCompiledClasses in Aspectj).value,
// ignore warnings
aspectjLintProperties in Aspectj += "invalidAbsoluteTypeName = ignore",
aspectjLintProperties in Aspectj += "adviceDidNotMatch = ignore",
// replace regular products with compiled aspects
products in Compile := (products in Aspectj).value
)
// test that the instrumentation works
lazy val instrumented = (project in file("instrumented"))
.enablePlugins(SbtAspectj)
.settings(buildSettings)
.settings(
// add the compiled aspects from tracer
aspectjBinaries in Aspectj ++= (products in Compile in tracer).value,
// weave this project's classes
aspectjInputs in Aspectj += (aspectjCompiledClasses in Aspectj).value,
products in Compile := (products in Aspectj).value,
products in Runtime := (products in Compile).value
).dependsOn(tracer)
// for sbt scripted test:
TaskKey[Unit]("check") := {
import scala.sys.process.Process
val cp = (fullClasspath in Compile in instrumented).value
val mc = (mainClass in Compile in instrumented).value
val opts = (javaOptions in run in Compile in instrumented).value
val expected = "Printing sample:\nhello\n"
val output = Process("java", opts ++ Seq("-classpath", cp.files.absString, mc getOrElse "")).!!
if (output != expected) {
println("Unexpected output:")
println(output)
println("Expected:")
println(expected)
sys.error("Unexpected output")
} else {
print(output)
}
}
但是当我 运行 sbt 编译时,这个错误突然出现:
Weaving 1 input to ,<path>\SpringIn28Minutes-master\SpringIn28Minutes-master\testingAspectScalaFullexample\tracer\target\scala-2.12\aspectj\classes...
[error] error can't determine superclass of missing type java.lang.Object
[error] when batch building BuildConfig[null] #Files=0 AopXmls=#0
[error] [Xlint:cantFindType]
[error] org.aspectj.bridge.AbortException: AspectJ failed
[error] at com.lightbend.sbt.SbtAspectj$Ajc$.runAjcMain(SbtAspectj.scala:212)
[error] at com.lightbend.sbt.SbtAspectj$Ajc$.runAjc(SbtAspectj.scala:124)
[error] at com.lightbend.sbt.SbtAspectj$Ajc$.$anonfun$ajcTask(SbtAspectj.scala:111)
[error] at sbt.util.FileFunction$.$anonfun$cached(FileFunction.scala:80)
[error] at sbt.util.FileFunction$.$anonfun$cached(FileFunction.scala:153)
[error] at sbt.util.Difference.apply(Tracked.scala:414)
[error] at sbt.util.Difference.apply(Tracked.scala:394)
[error] at sbt.util.FileFunction$.$anonfun$cached(FileFunction.scala:149)
[error] at sbt.util.Difference.apply(Tracked.scala:414)
[error] at sbt.util.Difference.apply(Tracked.scala:389)
[error] at sbt.util.FileFunction$.$anonfun$cached(FileFunction.scala:148)
[error] at com.lightbend.sbt.SbtAspectj$Ajc$.$anonfun$ajcTask(SbtAspectj.scala:116)
[error] at scala.Function1.$anonfun$compose(Function1.scala:49)
[error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219(TypeFunctions.scala:62)
[error] at sbt.std.Transform$$anon.work(Transform.scala:68)
[error] at sbt.Execute.$anonfun$submit(Execute.scala:282)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] at sbt.Execute.work(Execute.scala:291)
[error] at sbt.Execute.$anonfun$submit(Execute.scala:282)
[error] at sbt.ConcurrentRestrictions$$anon.$anonfun$submitValid(ConcurrentRestrictions.scala:265)
[error] at sbt.CompletionService$$anon.call(CompletionService.scala:64)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executo
rs.java:515)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoo
lExecutor.java:1130)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPo
olExecutor.java:630)
[error] at java.base/java.lang.Thread.run(Thread.java:831)
[error] (tracer / Aspectj / ajc) org.aspectj.bridge.AbortException: AspectJ failed
好的,您正在使用插件源代码存储库中的 this example。你为什么不直接说 link 呢?你让它看起来好像你自己创建了样本。我找到了它,还有你在这里做的 而不是 post project/plugins.sbt
。就像我之前在聊天中告诉你的那样,我是一个 Scala 菜鸟,我这辈子都没有用过它,也不知道文件丢失了。那花了我很多时间。为什么您 post 在这里 post 一个不完整的示例项目,而不是像我要求的那样在 GitHub 上发布它?然后我就可以克隆该项目并 运行 它。直到我在网上找到示例代码,我才意识到你的代码不完整。
另外,我的IDEIntelliJ IDEA无法导入示例工程,一定是当前版本有什么bug。我只能从 sbt shell 编译和 运行。在那里,我终于可以重现你的问题了。
其实原因很简单:插件已过时,请尽快更新。它依赖于仅支持 Java 8 的 AspectJ Compiler Tools 1.8.10。它甚至不是最新的 1.8 版本,应该是 1.8.13。此外,该插件将 AspectJ Runtime 1.8.10 作为 运行 时间依赖项导出到使用该插件的项目。另见:
- https://github.com/sbt/sbt-aspectj/blob/8ff3a1ad4224934dabe222205eb89c985670f240/build.sbt#L7
- https://github.com/sbt/sbt-aspectj/blob/8ff3a1ad4224934dabe222205eb89c985670f240/src/main/scala/com/lightbend/sbt/SbtAspectj.scala#L30
只要您在 JDK 1.8 上编译并 运行 您的项目,一切都很好。如果您使用更新的 JDK,解决方案是覆盖依赖项。将其放入 project/plugins.sbt
:
addSbtPlugin("org.jetbrains" % "sbt-ide-settings" % "1.1.0")
addSbtPlugin("com.lightbend.sbt" % "sbt-aspectj" % "0.11.0")
dependencyOverrides += "org.aspectj" % "aspectjrt" % "1.9.6"
dependencyOverrides += "org.aspectj" % "aspectjtools" % "1.9.6"
AspectJ 1.9.6 最高支持语言级别 14。支持 Java15+16 的版本 1.9.7 即将发布。但是如果你在 JDK 16 上 运行,但编译到不高于目标 14,你应该没问题。
顺便说一句,测试是特定于平台的,在 Windows 上会失败,因为它需要 UNIX 行分隔符 (LF),而 Windows 使用 CR+LF:
val expected = "Printing sample:\nhello\n"
您应该将其更改为:
val LF = System.lineSeparator()
val expected = "Printing sample:" + LF + "hello" + LF
我正尝试在 IntelliJ 上使用 Scala 和 AspectJ 作为 IDE。 #文件结构
Sample.scala - (主要方法组成的class)
package sample
class SampleClass {
def printSample():Unit = println("hello")
}
object SampleObject extends App {
val sample = new SampleClass
sample.printSample()
}
Tracer.scala -(Tracer 功能或换句话说方面)
package sample
import org.aspectj.lang.annotation._
@Aspect
class Tracer {
@Before("execution(* sample.SampleClass.printSample(..))")
def printSample() {
println("Printing sample:")
}
}
build.sbt - 为了 运行 sbt 命令(sbt 编译和 sbt 运行)
name := "testingAspectScalaFullexample"
version := "0.1"
scalaVersion := "2.13.5"
lazy val buildSettings = Seq(
organization := "com.lightbend.sbt.aspectj",
version := "0.1-SNAPSHOT",
scalaVersion := "2.12.1"
)
lazy val sample = (project in file("."))
.settings(buildSettings)
.aggregate(tracer, instrumented)
// precompiled aspects
lazy val tracer = (project in file("tracer"))
.enablePlugins(SbtAspectj)
.settings(buildSettings)
.settings(
// input compiled scala classes
aspectjInputs in Aspectj += (aspectjCompiledClasses in Aspectj).value,
// ignore warnings
aspectjLintProperties in Aspectj += "invalidAbsoluteTypeName = ignore",
aspectjLintProperties in Aspectj += "adviceDidNotMatch = ignore",
// replace regular products with compiled aspects
products in Compile := (products in Aspectj).value
)
// test that the instrumentation works
lazy val instrumented = (project in file("instrumented"))
.enablePlugins(SbtAspectj)
.settings(buildSettings)
.settings(
// add the compiled aspects from tracer
aspectjBinaries in Aspectj ++= (products in Compile in tracer).value,
// weave this project's classes
aspectjInputs in Aspectj += (aspectjCompiledClasses in Aspectj).value,
products in Compile := (products in Aspectj).value,
products in Runtime := (products in Compile).value
).dependsOn(tracer)
// for sbt scripted test:
TaskKey[Unit]("check") := {
import scala.sys.process.Process
val cp = (fullClasspath in Compile in instrumented).value
val mc = (mainClass in Compile in instrumented).value
val opts = (javaOptions in run in Compile in instrumented).value
val expected = "Printing sample:\nhello\n"
val output = Process("java", opts ++ Seq("-classpath", cp.files.absString, mc getOrElse "")).!!
if (output != expected) {
println("Unexpected output:")
println(output)
println("Expected:")
println(expected)
sys.error("Unexpected output")
} else {
print(output)
}
}
但是当我 运行 sbt 编译时,这个错误突然出现:
Weaving 1 input to ,<path>\SpringIn28Minutes-master\SpringIn28Minutes-master\testingAspectScalaFullexample\tracer\target\scala-2.12\aspectj\classes...
[error] error can't determine superclass of missing type java.lang.Object
[error] when batch building BuildConfig[null] #Files=0 AopXmls=#0
[error] [Xlint:cantFindType]
[error] org.aspectj.bridge.AbortException: AspectJ failed
[error] at com.lightbend.sbt.SbtAspectj$Ajc$.runAjcMain(SbtAspectj.scala:212)
[error] at com.lightbend.sbt.SbtAspectj$Ajc$.runAjc(SbtAspectj.scala:124)
[error] at com.lightbend.sbt.SbtAspectj$Ajc$.$anonfun$ajcTask(SbtAspectj.scala:111)
[error] at sbt.util.FileFunction$.$anonfun$cached(FileFunction.scala:80)
[error] at sbt.util.FileFunction$.$anonfun$cached(FileFunction.scala:153)
[error] at sbt.util.Difference.apply(Tracked.scala:414)
[error] at sbt.util.Difference.apply(Tracked.scala:394)
[error] at sbt.util.FileFunction$.$anonfun$cached(FileFunction.scala:149)
[error] at sbt.util.Difference.apply(Tracked.scala:414)
[error] at sbt.util.Difference.apply(Tracked.scala:389)
[error] at sbt.util.FileFunction$.$anonfun$cached(FileFunction.scala:148)
[error] at com.lightbend.sbt.SbtAspectj$Ajc$.$anonfun$ajcTask(SbtAspectj.scala:116)
[error] at scala.Function1.$anonfun$compose(Function1.scala:49)
[error] at sbt.internal.util.$tilde$greater.$anonfun$$u2219(TypeFunctions.scala:62)
[error] at sbt.std.Transform$$anon.work(Transform.scala:68)
[error] at sbt.Execute.$anonfun$submit(Execute.scala:282)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] at sbt.Execute.work(Execute.scala:291)
[error] at sbt.Execute.$anonfun$submit(Execute.scala:282)
[error] at sbt.ConcurrentRestrictions$$anon.$anonfun$submitValid(ConcurrentRestrictions.scala:265)
[error] at sbt.CompletionService$$anon.call(CompletionService.scala:64)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executo
rs.java:515)
[error] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoo
lExecutor.java:1130)
[error] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPo
olExecutor.java:630)
[error] at java.base/java.lang.Thread.run(Thread.java:831)
[error] (tracer / Aspectj / ajc) org.aspectj.bridge.AbortException: AspectJ failed
好的,您正在使用插件源代码存储库中的 this example。你为什么不直接说 link 呢?你让它看起来好像你自己创建了样本。我找到了它,还有你在这里做的 而不是 post project/plugins.sbt
。就像我之前在聊天中告诉你的那样,我是一个 Scala 菜鸟,我这辈子都没有用过它,也不知道文件丢失了。那花了我很多时间。为什么您 post 在这里 post 一个不完整的示例项目,而不是像我要求的那样在 GitHub 上发布它?然后我就可以克隆该项目并 运行 它。直到我在网上找到示例代码,我才意识到你的代码不完整。
另外,我的IDEIntelliJ IDEA无法导入示例工程,一定是当前版本有什么bug。我只能从 sbt shell 编译和 运行。在那里,我终于可以重现你的问题了。
其实原因很简单:插件已过时,请尽快更新。它依赖于仅支持 Java 8 的 AspectJ Compiler Tools 1.8.10。它甚至不是最新的 1.8 版本,应该是 1.8.13。此外,该插件将 AspectJ Runtime 1.8.10 作为 运行 时间依赖项导出到使用该插件的项目。另见:
- https://github.com/sbt/sbt-aspectj/blob/8ff3a1ad4224934dabe222205eb89c985670f240/build.sbt#L7
- https://github.com/sbt/sbt-aspectj/blob/8ff3a1ad4224934dabe222205eb89c985670f240/src/main/scala/com/lightbend/sbt/SbtAspectj.scala#L30
只要您在 JDK 1.8 上编译并 运行 您的项目,一切都很好。如果您使用更新的 JDK,解决方案是覆盖依赖项。将其放入 project/plugins.sbt
:
addSbtPlugin("org.jetbrains" % "sbt-ide-settings" % "1.1.0")
addSbtPlugin("com.lightbend.sbt" % "sbt-aspectj" % "0.11.0")
dependencyOverrides += "org.aspectj" % "aspectjrt" % "1.9.6"
dependencyOverrides += "org.aspectj" % "aspectjtools" % "1.9.6"
AspectJ 1.9.6 最高支持语言级别 14。支持 Java15+16 的版本 1.9.7 即将发布。但是如果你在 JDK 16 上 运行,但编译到不高于目标 14,你应该没问题。
顺便说一句,测试是特定于平台的,在 Windows 上会失败,因为它需要 UNIX 行分隔符 (LF),而 Windows 使用 CR+LF:
val expected = "Printing sample:\nhello\n"
您应该将其更改为:
val LF = System.lineSeparator()
val expected = "Printing sample:" + LF + "hello" + LF