package language; public class Initialization { public static void main(String[] argList) { String[] expected = new String[] { "none after-String-constructor-execution after-initialization after-any-constructor-call", "hello after-String-constructor-execution after-initialization after-any-constructor-call", "none after-String-constructor-execution after-initialization", "hi from-AnotherThing after-String-constructor-execution after-initialization" }; String[] actual = new String[4]; Thing thing = new Thing(); actual[0] = new Thing().message; actual[1] = new Thing("hello").message; actual[2] = new AnotherThing().message; actual[3] = new AnotherThing("hi").message; StringBuffer errs = new StringBuffer(); for (int i = 0; i < actual.length; i++) { if (!expected[i].equals(actual[i])) { errs.append("expected "); errs.append(expected[i]); errs.append(" but got "); errs.append(actual[i]); errs.append("\n"); } } if (0 < errs.length()) { throw new Error(errs.toString()); } } } /** @author Erik Hilsdale, Wes Isberg */ // START-SAMPLE language-initialization Understanding object creation join points /* * To work with an object right when it is constructed, * understand the differences between the join points for * constructor call, constructor execution, and initialization. */ // ------- examples of constructors and the ways they invoke each other. class Thing { String message; Thing() { this("none"); } Thing(String message) { this.message = message; } } class AnotherThing extends Thing { AnotherThing() { super(); // this does not append to message as the one below does. } AnotherThing(String message) { super(message + " from-AnotherThing"); } } aspect InitializationSample { // -------- constructor-call picks out the calls /** * After any call to any constructor, fix up the thing. * When creating an object, there is only one call to * construct it, so use call(..) avoid duplicate advice. * There is no target for the call, but the object * constructed is returned from the call. * In AspectJ 1.1, this only picks out callers in the input * classes or source files, and it does not pick out * invocations via super(..) * or this(..). */ after() returning (Thing thing): call(Thing.new(..)) { thing.message += " after-any-constructor-call"; } // -------- constructor-execution picks out each body /** * After executing the String constructor, fix up the thing. * The object being-constructed is available as either * this or target. * This works even if the constructor was invoked using * super() or this() or by code * outside the control of the AspectJ compiler. * However, if you advise multiple constructors, you'll advise * a single instance being constructed multiple times * if the constructors call each other. * In AspectJ 1.1, this only affects constructors in the input * classes or source files. */ after(Thing thing) returning : target(thing) && execution(Thing.new(String)) { thing.message += " after-String-constructor-execution"; } /** * DANGER -- BAD!! Before executing the String constructor, * this uses the target object, which is not constructed. */ before (Thing thing): this(thing) && execution(Thing.new(String)) { // DANGER!! thing not constructed yet. //thing.message += " before-String-constructor-execution"; } // -------- initialization picks out any construction, once /** * This advises all Thing constructors in one join point, * even if they call each other with this(), etc. * The object being-constructed is available as either * this or target. * In AspectJ 1.1, this only affects types input to the compiler. */ after(Thing thing) returning: this(thing) && initialization(Thing.new(..)) { thing.message += " after-initialization"; } } //END-SAMPLE language-initialization aspect B { static boolean log = false; before() : withincode(void Initialization.main(String[])) && call(Thing.new(..)) && if(log) { System.out.println("before: " + thisJoinPointStaticPart.getSourceLocation().getLine()); } before() : within(A) && adviceexecution() && if(log) { System.out.println("advice: " + thisJoinPointStaticPart.getSourceLocation().getLine()); } }