From 57729634e86cfb608f440b6b4a67c37e13f3b54b Mon Sep 17 00:00:00 2001 From: wisberg Date: Sat, 6 Sep 2003 23:58:30 +0000 Subject: [PATCH] initialization example: more comments and more testable --- .../common/language/Initialization.java | 118 ++++++++++++------ 1 file changed, 78 insertions(+), 40 deletions(-) diff --git a/docs/sandbox/common/language/Initialization.java b/docs/sandbox/common/language/Initialization.java index 46d3ec872..20c308de9 100644 --- a/docs/sandbox/common/language/Initialization.java +++ b/docs/sandbox/common/language/Initialization.java @@ -3,21 +3,31 @@ 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(); - if (12 != thing.counter) { - System.err.println("expected 12, got " + thing.counter); + 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"); + } } - thing = new Thing(20); - if (32 != thing.counter) { - System.err.println("expected 32, got " + thing.counter); - } - thing = new AnotherThing(); - if (2 != thing.counter) { - System.err.println("expected 2, got " + thing.counter); - } - thing = new AnotherThing(20); - if (23 != thing.counter) { - System.err.println("expected 23, got " + thing.counter); + if (0 < errs.length()) { + throw new Error(errs.toString()); } } } @@ -29,67 +39,95 @@ public class Initialization { * 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 { - int counter; + String message; Thing() { - this(1); + this("none"); } - Thing(int value) { - counter = value; + Thing(String message) { + this.message = message; } } class AnotherThing extends Thing { AnotherThing() { - super(); + super(); // this does not append to message as the one below does. } - AnotherThing(int i) { - super(++i); + AnotherThing(String message) { + super(message + " from-AnotherThing"); } } aspect A { + // -------- constructor-call picks out the calls /** * After any call to any constructor, fix up the thing. - * In AspectJ 1.1, this only affects callers in the input - * classes or source files, but not super calls. + * 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(..)) { - postInitialize(thing); + thing.message += " after-any-constructor-call"; } + // -------- constructor-execution picks out each body /** - * After executing the int constructor, fix up the thing. - * This works regardless of how the constructor was called - * (by outside code or by super), but only for the - * specified constructors. + * 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() returning (Thing thing): execution(Thing.new(int)) { - thing.counter++; + after(Thing thing) returning : target(thing) && + execution(Thing.new(String)) { + thing.message += " after-String-constructor-execution"; } /** - * DANGER -- BAD!! Before executing the int constructor, + * DANGER -- BAD!! Before executing the String constructor, * this uses the target object, which is not constructed. */ - before (Thing thing): this(thing) && execution(Thing.new(int)) { - // thing.counter++; // DANGER!! thing not constructed yet. + 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(). - */ + * 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.counter++; - } - - protected void postInitialize(Thing thing) { - thing.counter += 10; + 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()); + } +} -- 2.39.5