]> source.dussan.org Git - aspectj.git/commitdiff
initialization example: more comments and more testable
authorwisberg <wisberg>
Sat, 6 Sep 2003 23:58:30 +0000 (23:58 +0000)
committerwisberg <wisberg>
Sat, 6 Sep 2003 23:58:30 +0000 (23:58 +0000)
docs/sandbox/common/language/Initialization.java

index 46d3ec872998a3269e3a8cdd7aa25f380bddb2a9..20c308de94aff012cb97c7c53fc8d1ee00b1ab89 100644 (file)
@@ -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 <code>super(..)</code> 
+     * or <code>this(..)</code>.
      */
     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
+     * <code>this</code> or <code>target</code>.
+     * This works even if the constructor was invoked using 
+     * <code>super()</code> or <code>this()</code> 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 <code>this()</code>, etc.
+     * The object being-constructed is available as either
+     * <code>this</code> or <code>target</code>.
+     * 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());
+    }
+}