1

在 Java 中,我们可以使用AspectJ透明地向 Java 类添加日志记录(或者可能使用其他字节码检测工具)。现在我想知道如何将日志透明地添加到Scala函数中。

我想要一个转换功能的工具foo

def foo(x:Int) = x + 1

像这样的东西:

def foo(x:Int) = {
   log.trace("Enter foo with x = " + x) // 自动添加
   val r = x + 1
   log.trace("Exit foo with r = " + r) // 自动添加  
   r
}

您将如何将日志记录透明地添加到 Scala 函数中?

4

1 回答 1

2

AspectJ 可以很好地处理 Scala 代码。您只需要遵循 Scala 名称修改规则(即def >变为def $gt)等等。

假设你有

class Foo {
  def foo(x: Int) {
  }
  def bar() { }
}

要添加日志记录,您可以使用 Java AspectJ 语法,添加

"org.aspectj" % "aspectjweaver" % "1.7.2",
"org.aspectj" % "aspectjrt" % "1.7.2"

给你的build.sbt. 继续前进,您可以有以下方面:

@Aspect
public class MonitorAspect {

    @Pointcut(value = "execution (* your.package.Foo.*(..))")
    public void methodsInFoo() {}

    @Before("methodsInFoo()")
    public void enter(JoinPoint jp) {
        // log
    }

    @After("methodsInFoo()")
    public void exit(JoinPoint jp) {
    }
}

最后一部分是META-INF/aop.xml,它定义了加载时编织器的工作:

<aspectj>

    <aspects>
        <aspect name="your.package.MonitorAspect"/>
    </aspects>

    <weaver options="-XnoInline">
        <include within="your.package.*"/>
    </weaver>

</aspectj>

最后,启动您的 JVM,-javaagent:$PATH_TO_ASPECTJWEAVER.JAR一切就绪。


在您的情况下,可能值得考虑使用高阶函数。如果您仅使用日志记录作为示例,并且如果您实际上是在某个内部函数之前之后做某事,那么您应该考虑使用 HOF。

def logged[U](f: => U): U = {
    log.info("Before")
    val ret = f
    log.info("After")
    ret
}

在这里,你有一个logged函数,它接受另一个函数f,处理日志并做任何事情f

于 2013-06-02T09:22:40.953 回答