Переглянути джерело

initialization example: more comments and more testable

tags/V1_1_1
wisberg 21 роки тому
джерело
коміт
57729634e8
1 змінених файлів з 78 додано та 40 видалено
  1. 78
    40
      docs/sandbox/common/language/Initialization.java

+ 78
- 40
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 <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());
}
}

Завантаження…
Відмінити
Зберегти