New, better version:
Well, while the old version below actually catches all constructor executions, an around
advice on constructor execution returns null because the object in question has not been initialised yet. So you would end up with a map of null pointers in your aspect. In order to fix this you need to bind this()
to a variable (sample code uses default package name):
public class Application {
public static void main(String[] args) throws Exception {
new Circle().draw();
((Shape) Class.forName("Triangle").getConstructor().newInstance()).isDrawn();
((Shape) Class.forName("Square").getConstructor().newInstance()).erase();
}
}
import java.util.HashMap;
import java.util.Map;
public aspect ShapeHolderAspect {
private Map<Integer, Shape> map = new HashMap<Integer, Shape>();
private int count = 0;
after(Shape shape): execution(Shape+.new(..)) && this(shape) {
System.out.println(thisJoinPointStaticPart);
map.put(++count, shape);
}
after() : execution(* Application.main(..)) {
System.out.println("\nList of shapes:");
for (int key : map.keySet())
System.out.println(" " + key + " -> " + map.get(key));
}
}
The output looks like this:
initialization(Circle())
initialization(Triangle())
initialization(Square())
List of shapes:
1 -> Circle@1a2961b
2 -> Triangle@12d03f9
3 -> Square@5ffb18
BTW, if you absolutely need an around
advice because you want to do other things before and after object creation, it would look like this:
void around(Shape shape): execution(Shape+.new(..)) && this(shape) {
System.out.println(thisJoinPointStaticPart);
proceed(shape);
map.put(++count, shape);
}
Old, incomplete version:
Quite simply, just intercept constructor execution
instead of call
:
pointcut shapeInit(): execution(Shape+.new(..));
This way you weave into the called code (callee), not the calling code (caller). Consequently, it does not matter if the caller issues a reflective or normal call.