Today I was writing an AspectJ aspect for a Scala trait and was wondering why my constructor pointcut definition didn't work. Having a closer look at the Scala byte code together with my colleague Johan solved the puzzle. Here is what I did (using AspectJ 1.6.8 and Scala 2.8.Beta1):
To start with here's a simplified version of the trait that I wanted to intercept:
trait MyTrait {
var someStuff = "someStuff"
def someMethod() : String = {
"do something"
}
}
class SomeClass extends MyTrait
As I wanted to intercept the constructor and some method calls I defined my aspect like this:
public aspect MyAspect {
public pointcut newInstance() : execution(MyTrait+.new(..));
public pointcut someInvocation() : execution(String MyTrait+.someMethod(..));
after() : newInstance() {
System.out.println("after MyTrait constructor invocation");
}
after() : someInvocation() {
System.out.println("after someMethod invocation");
}
}
Runnning the code I got quite puzzled that the method invocation pointcut worked fine, but not the constructor pointcut. After consulting the AspectJ reference and convincing myself that the pointcut definition was ok, I had a closer look at the byte code. As we don't have traits in Java the byte code for my trait becomes equivalent to the following pseudo-javacode:
public interface MyTrait extends scala.ScalaObject{
public String someMethod();
}
public abstract class MyTrait$class extends java.lang.Object{
public static String someMethod(MyTrait myTrait) {
// invoke someMethod
}
public static void $init$(MyTrait myTrait) {
// some init stuff
}
}
So in bytecode I've got an interface and a class with some static method calls. The stuff that goes in the constructor of my trait is done in the $init$ method of the MyTrait$class class. And that's the reason why my pointcut won't work. So actually I have to intercept the $init$ method of the MyTrait$class to get what i want:
public pointcut newInstance() : execution(void MyTrait$class.$init$(..));
Michael Kober
Consultant at Jayway

1 comment so far ↓
looks like u’r trying to compromise whole idea behind the traits
why don’t u use classes instead
Leave a Comment