AspectJ will work just fine with Scala code. You'll just need to follow the Scala name mangling rules (i.e. def > becomes def $gt) and so on.
Suppose you have
class Foo {
def foo(x: Int) {
}
def bar() { }
}
To add logging, you can use the Java AspectJ syntax, adding
"org.aspectj" % "aspectjweaver" % "1.7.2",
"org.aspectj" % "aspectjrt" % "1.7.2"
To your build.sbt. Moving on, you can have the following aspect:
@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) {
}
}
The final piece will be the META-INF/aop.xml, which defines the work for the load-time weaver:
<aspectj>
<aspects>
<aspect name="your.package.MonitorAspect"/>
</aspects>
<weaver options="-XnoInline">
<include within="your.package.*"/>
</weaver>
</aspectj>
Finally, start your JVM with -javaagent:$PATH_TO_ASPECTJWEAVER.JAR and you're all set.
In your case, it may be worth thinking about using higher-order functions. If you are using logging as just an example, and if you're actually doing something before and after some inner function, you should consider using HOFs.
def logged[U](f: => U): U = {
log.info("Before")
val ret = f
log.info("After")
ret
}
Here, you have the logged function that takes another function f, deals with the logs and does whatever f does.