Hi,
I would like to execute some code at the very beginning and the end of every constructor... I'm using preinitialization and after returning as follows.
public aspect Foo {
pointcut allExecsNews() : execution(*.new(..)) && !within(Foo) ;
pointcut preInit() : preinitialization(*.new(..)) && !within(Foo);
before() : preInit() {
System.out.println("preinit " + thisJoinPoint.getSignature());
}
after() returning() : allExecsNews() {
System.out.println("after returning " + thisJoinPoint.getSignature());
}
}
applied to the following class
public class Reference {
Object a;
Object b;
Reference(Object a) {
this(a, null);
System.out.println("Ref");
}
Reference(Object a, Object b) {
this.a = a;
this.b = b;
System.out.println("Ref 2");
}
public static void main(String[] args) {
Reference r = new Reference(null);
}
}
I was expecting to have the following output:
preinit Reference(Object)
preinit Reference(Object, Object)
Ref 2
after returning Reference(Object, Object)
Ref
after returning Reference(Object)
However I obtain:
preinit Reference(Object)
Ref 2
after returning Reference(Object, Object)
Ref
after returning Reference(Object)
i.e. the invocation to preinit Reference(Object, Object) is missing... even though the pointcut is correctly captured by the aspect... !!!
Join point 'constructor-execution(void Reference.<init>(java.lang.Object))' in Type 'Reference' (Reference.java:8) advised by afterReturning advice from 'Foo' (Foo.java:10)
Join point 'constructor-execution(void Reference.<init>(java.lang.Object, java.lang.Object))' in Type 'Reference' (Reference.java:14) advised by afterReturning advice from 'Foo' (Foo.java:10)
Join point 'preinitialization(void Reference.<init>(java.lang.Object))' in Type 'Reference' (Reference.java:7) advised by before advice from 'Foo' (Foo.java:6)
Join point 'preinitialization(void Reference.<init>(java.lang.Object, java.lang.Object))' in Type 'Reference' (Reference.java:13) advised by before advice from 'Foo' (Foo.java:6)
By checking the generated bytecode, I realized that the body of the Reference(Object, Object) constructor was inlined directly in Reference(Object).. i.e. there is no longer the invocation to Reference(Object, Object) as in the original constructor..
The woven Reference(Object) has therefore:
- invocation to before preinit advice
- copy of the Reference(Object, Object) body <=== ???
- invocation to after (corresponding to Reference(Object,Object)) !!!
- invocation to after (correspoinding to Reference(Object)
The woven Reference(Object, Object) has:
- invocation to before preinit advice !!!
- body...
- invocation to after (corresponding to Reference(Object, Object)
Is this because I'm using after returning on the execution(*.new(..)) pointcut? or did I missed something?
If the constructor is inlined, why it doesn't inline also the invocation to before preinitalization as well? Is there a way to obtain the behaviour I want with other pointcuts? Is it because the object is not totally initialized?
Many thanks in advance.
Alex