diff options
author | Alexander Kriegisch <Alexander@Kriegisch.name> | 2021-07-16 10:48:06 +0700 |
---|---|---|
committer | Alexander Kriegisch <Alexander@Kriegisch.name> | 2024-01-06 10:09:11 +0100 |
commit | a6a1dbea46fd4829189b23fb900da6a586a8151a (patch) | |
tree | b6d8a3b4e38e320813566535c6ea4f036fb4ba91 /docs/dist/doc | |
parent | fa63feda31a6a9656173a63dc057993d98469305 (diff) | |
download | aspectj-a6a1dbea46fd4829189b23fb900da6a586a8151a.tar.gz aspectj-a6a1dbea46fd4829189b23fb900da6a586a8151a.zip |
Fix more AsciiDoc links and code blocks (WIP)
- Add Java syntax highlighting to AspectJ and Java files
- Add XML syntax highlighting to XML files (Ant, LTW etc.)
- Dedent and remove empty lines, where necessary
- Enclose in-line line numbers for Java code in /*23*/ comments in order
to enable Java formatting
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Diffstat (limited to 'docs/dist/doc')
26 files changed, 729 insertions, 646 deletions
diff --git a/docs/dist/doc/README-11.adoc b/docs/dist/doc/README-11.adoc index 377d18588..1843f38be 100644 --- a/docs/dist/doc/README-11.adoc +++ b/docs/dist/doc/README-11.adoc @@ -288,22 +288,21 @@ In AspectJ 1.0.6, we made an effort to hide some complications with Aspect instantiation from the user. In particular, the following code compiled and ran: +[source, java] .... - public class Client - { - public static void main(String[] args) { - Client c = new Client(); - } - } - - aspect Watchcall { - pointcut myConstructor(): execution(new(..)); +public class Client { + public static void main(String[] args) { + Client c = new Client(); + } +} - before(): myConstructor() { - System.err.println("Entering Constructor"); - } - } +aspect Watchcall { + pointcut myConstructor(): execution(new(..)); + before(): myConstructor() { + System.err.println("Entering Constructor"); + } +} .... But there's a conceptual problem with this code: The before advice @@ -317,25 +316,24 @@ preventing an aspect's advice from matching join points that were within the aspect's definition, and occurred before the aspect was initialized. But even in AspectJ 1.0.6, this circularity could be exposed: +[source, java] .... - public class Client - { - public static int foo() { return 3; } - public static void main(String[] args) { - Client c = new Client(); - } - } - - aspect Watchcall { - int i = Client.foo(); - pointcut myConstructor(): - execution(new(..)) || execution(int foo()); +public class Client { + public static int foo() { return 3; } + public static void main(String[] args) { + Client c = new Client(); + } +} - before(): myConstructor() { - System.err.println("Entering Constructor"); - } - } +aspect Watchcall { + int i = Client.foo(); + pointcut myConstructor(): + execution(new(..)) || execution(int foo()); + before(): myConstructor() { + System.err.println("Entering Constructor"); + } +} .... This program would throw a NullPointerException when run, since @@ -356,29 +354,29 @@ Type patterns may now be used to pick out methods and constructors based on their throws clauses. This allows the following two kinds of extremely wildcarded pointcuts: +[source, java] .... - pointcut throwsMathlike(): - // each call to a method with a throws clause containing at least - // one exception with "Math" in its name. - call(* *(..) throws *..*Math*); - - pointcut doesNotThrowMathlike(): - // each call to a method with a throws clause containing no - // exceptions with "Math" in its name. - call(* *(..) throws !*..*Math*); +pointcut throwsMathlike(): + // each call to a method with a throws clause containing at least + // one exception with "Math" in its name. + call(* *(..) throws *..*Math*); +pointcut doesNotThrowMathlike(): + // each call to a method with a throws clause containing no + // exceptions with "Math" in its name. + call(* *(..) throws !*..*Math*); .... The longwinded rules are that a method or constructor pattern can have a "throws clause pattern". Throws clause patterns look like: +[source, text] .... - ThrowsClausePattern: - ThrowsClausePatternItem ("," ThrowsClausePatternItem)* - - ThrowsClausePatternItem: - ["!"] TypeNamePattern +ThrowsClausePattern: + ThrowsClausePatternItem ("," ThrowsClausePatternItem)* +ThrowsClausePatternItem: + ["!"] TypeNamePattern .... A ThrowsClausePattern matches the ThrowsClause of any code member @@ -398,12 +396,12 @@ These rules are completely backwards compatible with AspectJ 1.0. The rule for "!" matching has one potentially surprising property, in that the two PCD's shown below will have different matching rules. +[source, java] .... - [1] call(* *(..) throws !IOException) - [2] call(* *(..) throws (!IOException)) - - void m() throws RuntimeException, IOException {} +/*[1]*/ call(* *(..) throws !IOException) +/*[2]*/ call(* *(..) throws (!IOException)) +void m() throws RuntimeException, IOException {} .... [1] will NOT match the method m(), because method m's throws clause @@ -439,31 +437,31 @@ xref:#SINGLE_INTERCLASS_TARGET[restrictions on inter-type declarations] . This is also motivated by many previous request to support a common logging idiom. Here's what pertype would look like: +[source, java] .... - /** One instance of this aspect will be created for each class, - * interface or aspect in the com.bigboxco packages. - */ - aspect Logger pertype(com.bigboxco..*) { - /* This field holds a logger for the class. */ - Log log; - - /* This advice will run for every public execution defined by - * a type for which a Logger aspect has been created, i.e. - * any type in com.bigboxco..* - */ - before(): execution(public * *(..)) { - log.enterMethod(thisJoinPoint.getSignature().getName()); - } +/** One instance of this aspect will be created for each class, + * interface or aspect in the com.bigboxco packages. + */ +aspect Logger pertype(com.bigboxco..*) { + /* This field holds a logger for the class. */ + Log log; - /* We can use a special constructor to initialize the log field */ - public Logger(Class myType) { - this.log = new Log(myType); - } + /* This advice will run for every public execution defined by + * a type for which a Logger aspect has been created, i.e. + * any type in com.bigboxco..* + */ + before(): execution(public * *(..)) { + log.enterMethod(thisJoinPoint.getSignature().getName()); } - /** External code could use aspectOf to get at the log, i.e. */ - Log l = Logger.aspectOf(com.bigboxco.Foo.class).log; + /* We can use a special constructor to initialize the log field */ + public Logger(Class myType) { + this.log = new Log(myType); + } +} +/** External code could use aspectOf to get at the log, i.e. */ +Log l = Logger.aspectOf(com.bigboxco.Foo.class).log; .... The one open question that we see is how this should interact with inner @@ -481,23 +479,23 @@ only have one target type. So the following code intended to declare that there is a void doStuff() method on all subtypes of Target is not legal AspectJ 1.1 code. +[source, java] .... - aspect A { - public void Target+.doStuff() { ... } - } - +aspect A { + public void Target+.doStuff() { ... } +} .... The functionality of "multi-intertype declarations" can be recovered by using a helper interface. +[source, java] .... - aspect A { - private interface MyTarget {} - declare parents: Target+ implements MyTarget; - public void MyTarget.doStuff() { ... } - } - +aspect A { + private interface MyTarget {} + declare parents: Target+ implements MyTarget; + public void MyTarget.doStuff() { ... } +} .... We believe this is better style in AspectJ 1.0 as well, as it makes @@ -531,18 +529,19 @@ The code generated by the initializers in Java source code now runs inside of constructor execution join points. This changes how before advice runs on constructor execution join points. Consider: +[source, java] .... - class C { - C() { } - String id = "identifier"; // this assignment - // has to happen sometime - } - aspect A { - before(C c) this(c) && execution(C.new()) { - System.out.println(c.id.length()); - } - } +class C { + C() { } + String id = "identifier"; // this assignment + // has to happen sometime +} +aspect A { + before(C c) this(c) && execution(C.new()) { + System.out.println(c.id.length()); + } +} .... In AspectJ 1.0, this will print "10", since id is assigned its initial @@ -579,10 +578,10 @@ initialization (i.e., before initializers from the target class) or at the end (i.e., just before its called constructor exits). We chose the former, having this pattern in mind: +[source, java] .... - int C.methodCount = 0; - before(C c): this(c) && execution(* *(..)) { c.methodCount++; } - +int C.methodCount = 0; +before(C c): this(c) && execution(* *(..)) { c.methodCount++; } .... We felt there would be too much surprise if a constructor called a @@ -604,25 +603,25 @@ C, below), if given a member-type (like C.InsideC, below), it is not guaranteed to capture code in contained local and anonymous types. For example: -.... - class C { - Thread t; - class InsideC { - void setupOuterThread() { - t = new Thread( - new Runnable() { - public void run() { - // join points with code here - // might not be captured by - // within(C.InsideC), but are - // captured by within(C) - System.out.println("hi"); - } - }); - } +[source, java] +.... +class C { + Thread t; + class InsideC { + void setupOuterThread() { + t = new Thread( + new Runnable() { + public void run() { + // join points with code here + // might not be captured by + // within(C.InsideC), but are + // captured by within(C) + System.out.println("hi"); + } + }); } } - +} .... We believe the non-guarantee is small, and we haven't verified that it @@ -642,9 +641,9 @@ their argument. These tests can not be performed on type patterns with wildcards in them. The following code that compiled under 1.0 will be an error in AspectJ-1.1: +[source, java] .... - pointcut oneOfMine(): this(com.bigboxco..*); - +pointcut oneOfMine(): this(com.bigboxco..*); .... The only way to implement this kind of matching in a modular way would @@ -653,27 +652,27 @@ would have a very high performance cost and possible security issues. There are two good work-arounds. If you control the source or bytecode to the type you want to match then you can use declare parents, i.e.: +[source, java] .... - private interface OneOfMine {} - declare parents: com.bigboxco..* implements OneOfMine; - pointcut oneOfMine(): this(OneOfMine); - +private interface OneOfMine {} +declare parents: com.bigboxco..* implements OneOfMine; +pointcut oneOfMine(): this(OneOfMine); .... If you want the more dynamic matching and are willing to pay for the performance, then you should use the Java reflection API combined with if. That would look something like: +[source, java] .... - pointcut oneOfMine(): this(Object) && - if(classMatches("com.bigboxco..*", - thisJoinPoint.getTarget().getClass())); - - static boolean classMatches(String pattern, Class _class) { - if (patternMatches(pattern, _class.getName())) return true; - ... - } +pointcut oneOfMine(): this(Object) && + if(classMatches("com.bigboxco..*", + thisJoinPoint.getTarget().getClass())); +static boolean classMatches(String pattern, Class _class) { + if (patternMatches(pattern, _class.getName())) return true; + ... +} .... Note: wildcard type matching still works in all other PCD's that match @@ -696,9 +695,9 @@ deprecated by the compiler, and will always return 0. AspectJ 1.1 has a new declare form: +[source, java] .... - declare precedence ":" TypePatternList ";" - +declare precedence ":" TypePatternList ";" .... This is used to declare advice ordering constraints on join points. For @@ -707,9 +706,9 @@ their name should dominate all other aspects, and (2) the Logging aspect (and any aspect that extends it) should dominate all non-security aspects, can be expressed by: +[source, java] .... - declare precedence: *..*Security*, Logging+, *; - +declare precedence: *..*Security*, Logging+, *; .... In the TypePatternList, the wildcard * means "any type not matched by @@ -720,19 +719,19 @@ another type in the declare precedence". It is an error for any aspect to be matched by more than one TypePattern in a single declare precedence, so: +[source, java] .... - declare precedence: A, B, A ; // error - +declare precedence: A, B, A ; // error .... However, multiple declare precedence forms may legally have this kind of circularity. For example, each of these declare precedence is perfectly legal: +[source, java] .... - declare precedence: B, A; - declare precedence: A, B; - +declare precedence: B, A; +declare precedence: A, B; .... And a system in which both constraints are active may also be legal, so @@ -743,33 +742,33 @@ idiom that can be used to enforce that A and B are strongly independent. Consider the following library aspects: +[source, java] .... - abstract aspect Logging { - abstract pointcut logged(); +abstract aspect Logging { + abstract pointcut logged(); - before(): logged() { - System.err.println("thisJoinPoint: " + thisJoinPoint); - } - } - - aspect MyProfiling { - abstract pointcut profiled(); + before(): logged() { + System.err.println("thisJoinPoint: " + thisJoinPoint); + } +} - Object around(): profiled() { - long beforeTime = System.currentTimeMillis(); - try { - return proceed(); - } finally { - long afterTime = System.currentTimeMillis(); - addToProfile(thisJoinPointStaticPart, - afterTime - beforeTime); - } - } - abstract void addToProfile( - org.aspectj.JoinPoint.StaticPart jp, - long elapsed); - } +aspect MyProfiling { + abstract pointcut profiled(); + Object around(): profiled() { + long beforeTime = System.currentTimeMillis(); + try { + return proceed(); + } finally { + long afterTime = System.currentTimeMillis(); + addToProfile(thisJoinPointStaticPart, + afterTime - beforeTime); + } + } + abstract void addToProfile( + org.aspectj.JoinPoint.StaticPart jp, + long elapsed); +} .... In order to use either aspect, they must be extended with concrete @@ -780,9 +779,9 @@ with the concrete aspect MyProfiling) without adding a dominates clause to Logging itself. In AspectJ 1.1, we can express that constraint with a simple: +[source, java] .... - declare precedence: MyLogging, MyProfiling; - +declare precedence: MyLogging, MyProfiling; .... ===== Changing order of advice for sub-aspects @@ -791,23 +790,23 @@ By default, advice in a sub-aspect has more precedence than advice in a super-aspect. One use of the AspectJ 1.0 dominates form was to change this precedence: +[source, java] .... - abstract aspect SuperA dominates SubA { - pointcut foo(): ... ; +abstract aspect SuperA dominates SubA { + pointcut foo(): ... ; - before(): foo() { - // in AspectJ 1.0, runs before the advice in SubA - // because of the dominates clause - } - } - - aspect SubA extends SuperA { - before(): foo() { - // in AspectJ 1.0, runs after the advice in SuperA - // because of the dominates clause - } - } + before(): foo() { + // in AspectJ 1.0, runs before the advice in SubA + // because of the dominates clause + } +} +aspect SubA extends SuperA { + before(): foo() { + // in AspectJ 1.0, runs after the advice in SuperA + // because of the dominates clause + } +} .... This no longer works in AspectJ 1.1, since declare precedence only @@ -827,10 +826,10 @@ So, if you have your project separated into a gui module and a base module, each of which is stored in a directory tree, you might use one of +[source, text] .... - ajc -sourceroots /myProject/gui:/myProject/base - ajc -sourceroots d:\myProject\gui;d:\myProject\base - +ajc -sourceroots /myProject/gui:/myProject/base +ajc -sourceroots d:\myProject\gui;d:\myProject\base .... This option may be used in conjunction with lst files, listing .java @@ -848,10 +847,10 @@ Windows). So, if MyTracing.java defines a trace aspect that you want to apply to all the classes in myBase.jar and myGui.jar, you would use one of: +[source, text] .... - ajc -injars /bin/myBase.jar:/bin/myGui.jar MyTracing.java - ajc -injars d:\bin\myBase.jar;d:\bin\myGui.jar MyTracing.java - +ajc -injars /bin/myBase.jar:/bin/myGui.jar MyTracing.java +ajc -injars d:\bin\myBase.jar;d:\bin\myGui.jar MyTracing.java .... The class files in the input jars must not have had advice woven into @@ -869,9 +868,9 @@ files on the command line, and the -sourceroots option. The -outjar option takes the name of a jar file into which the results of the compilation should be put. For example: +[source, text] .... - ajc -injars myBase.jar MyTracing.java -outjar myTracedBase.jar - +ajc -injars myBase.jar MyTracing.java -outjar myTracedBase.jar .... No meta information is placed in the output jar file. @@ -920,17 +919,17 @@ The binary forms of this aspects will be untouched. The 1.0 implementation of AspectJ, when given: +[source, java] .... - class MyRunnable implements Runnable { - public void run() { ... } - } +class MyRunnable implements Runnable { + public void run() { /*...*/ } +} - aspect A { - call(): (void run()) && target(MyRunnable) { - // do something here - } +aspect A { + call(): (void run()) && target(MyRunnable) { + // do something here } - +} .... would cause A's advice to execute even when, say, java.lang.Thread @@ -1117,14 +1116,14 @@ AspectJ 1.1 does not allow the inter-type definition of a zero-argument constructor on a class with a visible default constructor. So this is no longer allowed: +[source, java] .... - class C {} - - aspect A { - C.new() {} // was allowed in 1.0.6 - // is a "multiple definitions" conflict in 1.1 - } +class C {} +aspect A { + C.new() {} // was allowed in 1.0.6 + // is a "multiple definitions" conflict in 1.1 +} .... In the Java Programming Language, a class defined without a constructor @@ -1154,25 +1153,25 @@ The first two properties are important and are preserved in AspectJ 1.1, but the third property is and was ludicrous, and was never properly implemented (and never could be) in AspectJ 1.0.6. Consider: +[source, java] .... - interface Top0 {} - interface Top1 {} - interface I extends Top0, Top1 {} - interface J extends Top1, Top0 {} +interface Top0 {} +interface Top1 {} +interface I extends Top0, Top1 {} +interface J extends Top1, Top0 {} - class C implements I, J {} - // I says Top0's inits must run before Top1's - // J says Top1's inits must run before Top0's +class C implements I, J {} +// I says Top0's inits must run before Top1's +// J says Top1's inits must run before Top0's - aspect A { - int Top0.i = foo("I'm in Top0"); - int Top1.i = foo("I'm in Top1"); - static int foo(String s) { - System.out.println(s); - return 37; - } +aspect A { + int Top0.i = foo("I'm in Top0"); + int Top1.i = foo("I'm in Top1"); + static int foo(String s) { + System.out.println(s); + return 37; } - +} .... This was simply a bug in the AspectJ specification. The correct third @@ -1198,27 +1197,27 @@ not to return a value, but to simply assign a value. Thus, programmers typically wanted to write something like: +[source, java] .... - void around(): set(int Foo.i) { - if (theSetIsAllowed()) { - proceed(); - } +void around(): set(int Foo.i) { + if (theSetIsAllowed()) { + proceed(); } - +} .... And were confused by it being a compile-time error. They weren't confused for long, and soon adapted to writing: +[source, java] .... - int around(): set(int Foo.i) { - if (theSetIsAllowed()) { - return proceed(); - } else { - return Foo.i; - } +int around(): set(int Foo.i) { + if (theSetIsAllowed()) { + return proceed(); + } else { + return Foo.i; } - +} .... But there was definitely a short disconnect. @@ -1267,6 +1266,7 @@ implementation. In Java, the + operator sometimes results in StringBuffer objects being created, appended to, and used to generate a new String. Thus, +[source, java] .... class Foo { String makeEmphatic(String s) { @@ -1277,6 +1277,7 @@ class Foo { is approximately the same at runtime as +[source, java] .... class Foo { String makeEmphatic(String s) { @@ -1292,6 +1293,7 @@ discuss it), but in 1.1 we do. This change is likely to affect highly wildcarded aspects, and can do so in surprising ways. In particular: +[source, java] .... class A { before(int i): call(* *(int)) && args(i) { @@ -1303,6 +1305,7 @@ class A { may result in a stack overflow error, since the argument to println is really +[source, java] .... new StringBuffer("entering with ").append(i).toString() .... @@ -1310,6 +1313,7 @@ new StringBuffer("entering with ").append(i).toString() which has a call to StringBuffer.append(int). In such cases, it's worth restricting your pointcut, with something like one of: +[source, java] .... call(* *(int)) && args(i) && !within(A) call(* *(int)) && args(i) && !target(StringBuffer) @@ -1320,6 +1324,7 @@ call(* *(int)) && args(i) && !target(StringBuffer) Consider the following aspect +[source, java] .... public aspect SwingCalls { @@ -1333,9 +1338,10 @@ public aspect SwingCalls { And then consider the two statements +[source, java] .... - JFrame frame = new JFrame(); - frame.setTitle("Title"); +JFrame frame = new JFrame(); +frame.setTitle("Title"); .... According to the Java Language Specification version 2, the call to diff --git a/docs/dist/doc/README-12.adoc b/docs/dist/doc/README-12.adoc index 95775b45a..0b66b6556 100644 --- a/docs/dist/doc/README-12.adoc +++ b/docs/dist/doc/README-12.adoc @@ -139,21 +139,19 @@ returns false. Consider a simple tracing aspect as follows: +[source, java] .... +public aspect Tracing { - public aspect Tracing { + public static boolean enabled = false; - public static boolean enabled = false; + pointcut toBeTraced() : execution(* *(..)) || execution(new(..)); - pointcut toBeTraced() : execution(* *(..)) || execution(new(..)); - - before() : toBeTraced() && if(enabled) { - Object[] args = thisJoinPoint.getArgs(); - // format args and print out entry trace record etc.... - } + before() : toBeTraced() && if(enabled) { + Object[] args = thisJoinPoint.getArgs(); + // format args and print out entry trace record etc.... } - - +} .... The most important consideration is the system overhead when tracing is @@ -189,20 +187,20 @@ were passed to the compiler. For example, an error message arising as a result of a `declare error` statement might look as follows under AspectJ 1.1.1: +[source, text] .... - BadClass.java:6 should not be calling bad methods - +BadClass.java:6 should not be calling bad methods .... whereas in AspectJ 1.2 you will see: +[source, text] .... - BadClass.java:6 error should not be calling bad methods - new C().bad(); - ^^^^^^^^^^^^^^ - method-call(void C.bad()) - see also: DeclareError.java:5 - +BadClass.java:6 error should not be calling bad methods +new C().bad(); +^^^^^^^^^^^^^^ + method-call(void C.bad()) + see also: DeclareError.java:5 .... There are four new things to note about this error message. Firstly, @@ -220,13 +218,13 @@ When source code is not available, the messages show the binary input source (class file or jar file) in which the error or warning was detected: +[source, text] .... - BadClass.java:6 error should not be calling bad methods - (no source information available) - method-call(void C.bad()) - see also: C:\...\DeclareError.java:5 - see also: C:\...\bin-input.jar - +BadClass.java:6 error should not be calling bad methods +(no source information available) + method-call(void C.bad()) + see also: C:\...\DeclareError.java:5 + see also: C:\...\bin-input.jar .... This error message tells us that `BadClass.class` contained in a jar on @@ -240,38 +238,36 @@ line 5 of the file `DeclareError.java`. Consider the program: +[source, java] .... - - 01 class A { - 02 public void doIt() {...}; - 03 } - 04 - 05 class B extends A { - 06 public void doThisToo() {...}; - 07 } - 08 - 09 - 10 public class CallsAandB { - 11 - 12 public static void main(String[] args) { - 13 B b = new B(); - 14 A bInDisguise = new B(); - 15 - 16 b.doIt(); // AspectJ 1.2 matches here - 17 bInDisguise.doIt(); // this is never matched - 18 } - 19 - 20 } - 21 - 22 aspect CallPCDMatchingExample { - 23 - 24 before() : call(* B.doIt(..)) { - 25 System.out.println("About to call B.doIt(...)"); - 26 } - 27 - 28 } - - +/*01*/ class A { +/*02*/ public void doIt() {...}; +/*03*/ } +/*04*/ +/*05*/ class B extends A { +/*06*/ public void doThisToo() {...}; +/*07*/ } +/*08*/ +/*09*/ +/*10*/ public class CallsAandB { +/*11*/ +/*12*/ public static void main(String[] args) { +/*13*/ B b = new B(); +/*14*/ A bInDisguise = new B(); +/*15*/ +/*16*/ b.doIt(); // AspectJ 1.2 matches here +/*17*/ bInDisguise.doIt(); // this is never matched +/*18*/ } +/*19*/ +/*20*/ } +/*21*/ +/*22*/ aspect CallPCDMatchingExample { +/*23*/ +/*24*/ before() : call(* B.doIt(..)) { +/*25*/ System.out.println("About to call B.doIt(...)"); +/*26*/ } +/*27*/ +/*28*/ } .... Because the static type of `bInDisguise` is `A` (line 14), the call on @@ -287,19 +283,14 @@ designator does not match at a join point, and a user may have expected it to. Compiling the above program using AspectJ 1.2 produces the following compiler output: +[source, text] .... +CallsAandB.java:24 warning does not match because declaring type is A, if match desired use target(B) [Xlint:unmatchedSuperTypeInCall] +before() : call(* B.doIt(..)) { + ^^^^^^^^^^^^^^^ + see also: CallsAandB.java:17 - - CallsAandB.java:24 warning does not match because declaring type is A, if match desired use target(B) [Xlint:unmatchedSuperTypeInCall] - before() : call(* B.doIt(..)) { - ^^^^^^^^^^^^^^^ - see also: CallsAandB.java:17 - - - 1 warning - - - +1 warning .... The warning is telling us that the call pointcut associated with the @@ -385,38 +376,36 @@ Consider again the following example program which illustrates the differences in join point matching with the `call` pointcut designator between 1.4 and 1.3 compliance levels. +[source, java] .... - - 01 class A { - 02 public void doIt() {...}; - 03 } - 04 - 05 class B extends A { - 06 public void doThisToo() {...}; - 07 } - 08 - 09 - 10 public class CallsAandB { - 11 - 12 public static void main(String[] args) { - 13 B b = new B(); - 14 A bInDisguise = new B(); - 15 - 16 b.doIt(); // AspectJ 1.2 matches here - 17 bInDisguise.doIt(); // this is never matched - 18 } - 19 - 20 } - 21 - 22 aspect CallPCDMatchingExample { - 23 - 24 before() : call(* B.doIt(..)) { - 25 System.out.println("About to call B.doIt(...)"); - 26 } - 27 - 28 } - - +/*01*/ class A { +/*02*/ public void doIt() {...}; +/*03*/ } +/*04*/ +/*05*/ class B extends A { +/*06*/ public void doThisToo() {...}; +/*07*/ } +/*08*/ +/*09*/ +/*10*/ public class CallsAandB { +/*11*/ +/*12*/ public static void main(String[] args) { +/*13*/ B b = new B(); +/*14*/ A bInDisguise = new B(); +/*15*/ +/*16*/ b.doIt(); // AspectJ 1.2 matches here +/*17*/ bInDisguise.doIt(); // this is never matched +/*18*/ } +/*19*/ +/*20*/ } +/*21*/ +/*22*/ aspect CallPCDMatchingExample { +/*23*/ +/*24*/ before() : call(* B.doIt(..)) { +/*25*/ System.out.println("About to call B.doIt(...)"); +/*26*/ } +/*27*/ +/*28*/ } .... When this program is compiled with AspectJ 1.2 using the default @@ -492,20 +481,21 @@ sample application that demonstrates these capabilities. Following the instructions in the `README` file in that directory, running "`aj tracing.ExampleMain`" with `ASPECTPATH` unset produces the output: +[source, text] .... - c1.perimeter() = 12.566370614359172 - c1.area() = 12.566370614359172 - s1.perimeter() = 4.0 - s1.area() = 1.0 - c2.distance(c1) = 4.242640687119285 - s1.distance(c1) = 2.23606797749979 - s1.toString(): Square side = 1.0 @ (1.0, 2.0) - +c1.perimeter() = 12.566370614359172 +c1.area() = 12.566370614359172 +s1.perimeter() = 4.0 +s1.area() = 1.0 +c2.distance(c1) = 4.242640687119285 +s1.distance(c1) = 2.23606797749979 +s1.toString(): Square side = 1.0 @ (1.0, 2.0) .... If you set `ASPECTPATH` to include `../jars/tracingLib.jar`, and run "`aj tracing.ExampleMain`" again, the output will be: +[source, text] .... --> tracing.TwoDShape(double, double) <-- tracing.TwoDShape(double, double) @@ -542,7 +532,6 @@ s1.area() = 1.0 <-- double tracing.TwoDShape.getY() <-- double tracing.TwoDShape.distance(TwoDShape) etc... - .... The scripts only support JDK 1.4 and above - attempting to use them with diff --git a/docs/dist/doc/README-121.adoc b/docs/dist/doc/README-121.adoc index 74d4b3030..fd082ebcb 100644 --- a/docs/dist/doc/README-121.adoc +++ b/docs/dist/doc/README-121.adoc @@ -34,17 +34,18 @@ option, or set showweaveinfo=true in the iajc ant task. The following is an example of the messages produced when this option is enabled: +[source, text] .... - C:\aspectj1.2.1\doc\examples\tjp>ajc -showWeaveInfo *.java +C:\aspectj1.2.1\doc\examples\tjp>ajc -showWeaveInfo *.java - Type 'tjp.Demo' (Demo.java:20) advised by around advice from 'tjp.GetInfo' - (GetInfo.java:26) [RuntimeTest=true] +Type 'tjp.Demo' (Demo.java:20) advised by around advice from 'tjp.GetInfo' +(GetInfo.java:26) [RuntimeTest=true] - Type 'tjp.Demo' (Demo.java:30) advised by around advice from 'tjp.GetInfo' - (GetInfo.java:26) [RuntimeTest=true] +Type 'tjp.Demo' (Demo.java:30) advised by around advice from 'tjp.GetInfo' +(GetInfo.java:26) [RuntimeTest=true] - Type 'tjp.Demo' (Demo.java:34) advised by around advice from 'tjp.GetInfo' - (GetInfo.java:26) [RuntimeTest=true] +Type 'tjp.Demo' (Demo.java:34) advised by around advice from 'tjp.GetInfo' +(GetInfo.java:26) [RuntimeTest=true] .... === Dump Support @@ -91,11 +92,11 @@ detecting this performance related bug and for piloting the fix. String concatentation in declare error and warning statements is now supported. For example, you can write: +[source, java] .... - declare warning : jdbcCall() && !inDataLayer() - : "Please don't make calls to JDBC " + - "outside of the data layer."; - +declare warning : jdbcCall() && !inDataLayer() + : "Please don't make calls to JDBC " + + "outside of the data layer."; .... === Load-time Weaving Support diff --git a/docs/dist/doc/README-153.adoc b/docs/dist/doc/README-153.adoc index 8b1c065f1..422b34447 100644 --- a/docs/dist/doc/README-153.adoc +++ b/docs/dist/doc/README-153.adoc @@ -14,8 +14,7 @@ Notable changes since the 1.5.2 release include: + Until this release, the memory profile for AspectJ looked like this (time is along the X axis, memory usage is the Y axis) -`` - +[source, text] .... /\_ / \_ @@ -31,8 +30,7 @@ discarding them once woven and dumped to disk. In 1.5.3 we don't compile everything up front - we compile and weave files one at a time. Giving us this profile: -`` - +[source, text] .... /\ /\ /\ / \/ \/ \ @@ -46,6 +44,7 @@ to compile a project. For example, I have a 1000file project, affected by aspects at >750 join points. For given values of Xmx, here are the times taken to compile it (on the command line) with AspectJ1.5.2: +[source, text] .... Xmx Time 512M 33seconds @@ -58,6 +57,7 @@ The times gradually increase as the memory is reduced because the VM starts to thrash in garbage collection. Here are the results for AspectJ1.5.3: +[source, text] .... Xmx Time 512M 33s @@ -106,8 +106,7 @@ Concrete aspects defined using aop.xml are now exposed for weaving. It is now possible to ask an instance of a ptw aspect which type it is 'attached' to. The method: -`` - +[source, java] .... String getWithinTypeName() .... diff --git a/docs/dist/doc/README-160.adoc b/docs/dist/doc/README-160.adoc index cba5ce076..d62985634 100644 --- a/docs/dist/doc/README-160.adoc +++ b/docs/dist/doc/README-160.adoc @@ -35,6 +35,7 @@ parentheses around the parameter types in a method signature determine whether the annotations relate to the type of the parameter or the parameter itself. +[source, java] .... execution(* *(@A *)); .... @@ -42,12 +43,14 @@ execution(* *(@A *)); - Execution of a method/ctor whose first parameter is of a type annotated with @A. +[source, java] .... execution(* *(@A (*))); .... - Execution of a method/ctor whose first parameter is annotated with @A +[source, java] .... execution(* *(@A (@B *))) .... @@ -55,8 +58,9 @@ execution(* *(@A (@B *))) - Execution of a method/ctor whose first parameter is annotated with @A and is of a type annotated with @B. Example: +[source, java] .... ------- Start of Test.java ----- +// ------ Start of Test.java ----- @interface A {} @interface B {} @@ -69,7 +73,11 @@ aspect X { before(): execution(* *(@A (*))) {} before(): execution(* *(@B (*))) {} } ------- End of Test.java ----- +// ------ End of Test.java ----- +.... + +[source, text] +.... $ ajc -showWeaveInfo -1.6 Test.java Join point 'method-execution(void C.foo(java.lang.String))' in Type 'C' (A.java:5) advised by before advice from 'X' (A.java:10) @@ -78,9 +86,7 @@ Join point 'method-execution(void C.goo(java.lang.String))' in Type 'C' (A.java: Join point 'method-execution(void C.goo(java.lang.String))' in Type 'C' (A.java:6) advised by before advice from 'X' (A.java:10) .... -The first piece of advice matched both methods. The second only matched -goo(). + - + +The first piece of advice matched both methods. The second only matched `goo()`. ==== Annotation Value Matching @@ -93,13 +99,14 @@ has a particular value. Perhaps tracing has been turned on at the type level and a few critical methods should not get traced. Here is some code showing the use case: +[source, java] .... enum TraceLevel { NONE, LEVEL1, LEVEL2, LEVEL3 } @interface Trace { TraceLevel value() default TraceLevel.LEVEL1; } - + aspect X { // Advise all methods marked @Trace except those with a tracelevel of none before(): execution(@Trace !@Trace(TraceLevel.NONE) * *(..)) { diff --git a/docs/dist/doc/README-161.adoc b/docs/dist/doc/README-161.adoc index 2cea859bb..d4ef20cf4 100644 --- a/docs/dist/doc/README-161.adoc +++ b/docs/dist/doc/README-161.adoc @@ -146,8 +146,7 @@ If only binding an annotation at a method-execution join point in order to access an *enum value* within it, there is a more optimal syntax that can be used to produce faster code. Given this setup: -`` - +[source, java] .... enum Colour { RED,GREEN,BLUE;} @@ -159,6 +158,7 @@ public void colouredMethod() { } Current syntax: +[source, java] .... before(ColouredAnnotation anno): execution(* *(..)) && @annotation(anno) { printTheColour(anno.value()); @@ -167,12 +167,9 @@ before(ColouredAnnotation anno): execution(* *(..)) && @annotation(anno) { New optional syntax: -`` - +[source, java] .... before(Colour col): execution(* *(..)) && @annotation(ColouredAnnotation(col)) { printTheColour(col); } .... - -''''' diff --git a/docs/dist/doc/README-1610.adoc b/docs/dist/doc/README-1610.adoc index faf6b85d6..73d3dab90 100644 --- a/docs/dist/doc/README-1610.adoc +++ b/docs/dist/doc/README-1610.adoc @@ -23,6 +23,7 @@ project properties in eclipse and in the AspectJ Compiler section, scroll down to 'Other' and in the non-standard compiler options setting, specify: +[source, text] .... -Xset:minimalModel=true,typeDemotion=true .... diff --git a/docs/dist/doc/README-1611.adoc b/docs/dist/doc/README-1611.adoc index e240e36f4..d88609580 100644 --- a/docs/dist/doc/README-1611.adoc +++ b/docs/dist/doc/README-1611.adoc @@ -74,6 +74,7 @@ annotations, or modify existing annotations by changing their values. 1.6.11 includes a new piece of syntax that we are thinking might be appropriate for one of these scenarios. 1.6.11 supports this: +[source, java] .... declare @field: int Foo.i: -@Anno; .... @@ -89,6 +90,7 @@ but the inability to use it with binary weaving greatly reduced the usefulness. Fixes have gone into 1.6.11 to support binary weaving. What do we mean by intertype innertypes? Here is an example: +[source, java] .... class Foo { public void m() { diff --git a/docs/dist/doc/README-1612.adoc b/docs/dist/doc/README-1612.adoc index d69061257..78a90829a 100644 --- a/docs/dist/doc/README-1612.adoc +++ b/docs/dist/doc/README-1612.adoc @@ -43,13 +43,14 @@ added and for some cases there can be no need for that abstract aspect. This is a work in progress but now you can write this in the aop.xml: +[source, xml] .... <concrete-aspect name="MyAspect"> <before pointcut="execution(* Hello.say2(..)) AND args(message)" - invokeClass="SomeRegularJavaClass" + invokeClass="SomeRegularJavaClass" invokeMethod="someMethod(JoinPoint tjp, java.lang.String message)"/> <after pointcut="execution(* Hello.say2(..)) AND args(message)" - invokeClass="SomeRegularJavaClass" + invokeClass="SomeRegularJavaClass" invokeMethod="someOtherMethod(JoinPoint tjp, java.lang.String message)"/> </concrete-aspect> @@ -58,7 +59,7 @@ public class SomeRegularJavaClass { public static void someMethod(org.aspectj.lang.JoinPoint tjp, String s) { System.out.println("in advice4: s="+s+" at "+tjp); } - + public static void someOtherMethod(org.aspectj.lang.JoinPoint tjp, String s) { System.out.println("in advice5: s="+s+" at "+tjp); } @@ -101,8 +102,9 @@ get started! There is now a new well known name that you can use in the if clauses in your aspects. thisAspectInstance provides access to the aspect instance. -Here is an example: `` +Here is an example: +[source, java] .... aspect X { boolean doit() { @@ -116,10 +118,11 @@ aspect X { } .... -Now why not just use X.aspectOf() instead of thisAspectInstance? Well -thisAspectInstance is quite useful when working with abstract/concrete -aspects: `` +Now why not just use `X.aspectOf()` instead of `thisAspectInstance`? Well, +`thisAspectInstance` is quite useful when working with abstract/concrete +aspects: +[source, java] .... abstract aspect X { abstract pointcut p(); @@ -185,6 +188,7 @@ supports Java7 language constructs - that will happen after Eclipse It is now possible to specify synthetic in pointcuts: +[source, java] .... pointcut p(): execution(!synthetic * *(..)); .... @@ -210,6 +214,7 @@ use when you want to match upon the existence of an annotation but you don't need the annotation, you just need a value from it. This code snippet shows an example: +[source, java] .... @interface SomeAnnotation { int i(); @@ -227,6 +232,7 @@ binding too. Suppose the annotation had multiple int values, how would we select which int to bind? AspectJ will now use the name (if it can) to select the right value: +[source, java] .... @interface SomeAnnotation { int mods(); diff --git a/docs/dist/doc/README-164.adoc b/docs/dist/doc/README-164.adoc index b1de0e9b0..548cb086e 100644 --- a/docs/dist/doc/README-164.adoc +++ b/docs/dist/doc/README-164.adoc @@ -27,8 +27,7 @@ the full build times in AJDT: AJDT 1.6.3 (uses AspectJ 1.6.3) -`` - +[source, text] .... 21352ms 21597ms @@ -37,8 +36,7 @@ AJDT 1.6.3 (uses AspectJ 1.6.3) AJDT 1.6.5dev builds (use AspectJ 1.6.4) -`` - +[source, text] .... 19811ms 19802ms @@ -70,8 +68,7 @@ building code, weaving code. Initially this is using AJDT 1.6.2 (which embeds AspectJ 1.6.3): -`` - +[source, text] .... Type of change: adding a new method to a type Project build times (first one is the compile of our change, the rest are for downstream projects): @@ -88,8 +85,7 @@ Summary: Total time spent in the compiler for that change: 1597ms Now with AspectJ 1.6.5 dev builds (which embed AspectJ 1.6.4): -`` - +[source, text] .... Type of change: adding a new method to a type Project build times (first one is the compile of our change, the rest are for downstream projects): @@ -127,8 +123,9 @@ http://andrewclement.blogspot.com/2009/02/aspectj-fixing-reverse-cascade-errors. *Optimizing support for maintaining per join point state* The traditional way to maintain state on a per join point basis involves -using the JoinPoint.StaticPart as a key into a map: `` +using the JoinPoint.StaticPart as a key into a map: +[source, java] .... aspect X pertypewithin(*) { Map<JoinPoint.StaticPart,Timer> timerMap = ... @@ -149,8 +146,7 @@ points within a target type are unique (and start from 0) - they are ideal for array lookups. So using this the above aspect can be rewritten: -`` - +[source, java] .... aspect X pertypewithin(*) { Timer[] timerArray = ... @@ -189,17 +185,16 @@ target instance. The @DeclareMixin annotation is attached to a factory method which returns instances of the delegate. Here is a basic example: -`` - +[source, java] .... - // The factory method that can build the delegate instance is annotated with @DeclareMixin. - // The annotation value defines the type pattern for targets of the mixin. - // The parameter is the object for which a delegate is being constructed. - // The interface that will be mixed in is the return value of the factory method. - @DeclareMixin("org.xyz..*") - public static SomeInterface createDelegate(Object instance) { - return new SomeImplementation(instance); - } +// The factory method that can build the delegate instance is annotated with @DeclareMixin. +// The annotation value defines the type pattern for targets of the mixin. +// The parameter is the object for which a delegate is being constructed. +// The interface that will be mixed in is the return value of the factory method. +@DeclareMixin("org.xyz..*") +public static SomeInterface createDelegate(Object instance) { + return new SomeImplementation(instance); +} .... More examples are @@ -248,5 +243,3 @@ weaver. Although the type map uses Weak/Soft references to try and better control how it uses memory, the JVM policies for managing these references vary wildly and so some work needs to be done to allow for these differences. - -''''' diff --git a/docs/dist/doc/README-167.adoc b/docs/dist/doc/README-167.adoc index 66476f8cc..5a2a9ffcf 100644 --- a/docs/dist/doc/README-167.adoc +++ b/docs/dist/doc/README-167.adoc @@ -18,6 +18,7 @@ pointcut matching]. Basically by turning on the options '-timers -verbose' on the command line (or via Ant), output will be produced that looks a little like this: +[source, text] .... Pointcut matching cost (total=6532ms for 675000 joinpoint match calls): Time:482ms (jps:#168585) matching against @@ -102,8 +103,7 @@ that actually runs? One user, Oliver Hoff, raised a query on the performance of annotation binding. His case uncovered an old TODO left in the code a few years ago: -`` - +[source, text] .... // OPTIMIZE cache result of getDeclaredMethod and getAnnotation? .... @@ -121,29 +121,28 @@ value at an execution join point in different ways. The three scenarios look like this (where the annotation type is 'Marker' and it has a String value field called 'message'): -`` - +[source, java] .... - // CaseOne: annotation value fetching is done in the advice: - pointcut adviceRetrievesAnnotation(): execution(@Marker * runOne(..)); - before(): adviceRetrievesAnnotation() { - Marker marker = (Marker) ((MethodSignature) - thisJoinPointStaticPart.getSignature()).getMethod().getAnnotation(Marker.class); - String s = marker.message(); - } - - // CaseTwo: annotation binding is done in the pointcut, advice retrieves message - pointcut pointcutBindsAnnotation(Marker l): execution(@Marker * runTwo(..)) && @annotation(l); - before(Marker l): pointcutBindsAnnotation(l) { - String s = l.message(); - } - - // CaseThree: annotation binding directly targets the message value in the annotation - pointcut pointcutBindsAnnotationValue(String msg): - execution(@Marker * runThree(..)) && @annotation(Marker(msg)); - before(String s): pointcutBindsAnnotationValue(s) { - // already got the string - } +// CaseOne: annotation value fetching is done in the advice: +pointcut adviceRetrievesAnnotation(): execution(@Marker * runOne(..)); +before(): adviceRetrievesAnnotation() { + Marker marker = (Marker) ((MethodSignature) + thisJoinPointStaticPart.getSignature()).getMethod().getAnnotation(Marker.class); + String s = marker.message(); +} + +// CaseTwo: annotation binding is done in the pointcut, advice retrieves message +pointcut pointcutBindsAnnotation(Marker l): execution(@Marker * runTwo(..)) && @annotation(l); +before(Marker l): pointcutBindsAnnotation(l) { + String s = l.message(); +} + +// CaseThree: annotation binding directly targets the message value in the annotation +pointcut pointcutBindsAnnotationValue(String msg): + execution(@Marker * runThree(..)) && @annotation(Marker(msg)); +before(String s): pointcutBindsAnnotationValue(s) { + // already got the string +} .... Before 1.6.7, case 2 was slower than case 1 and case 3 wasn't supported @@ -157,8 +156,7 @@ stress the AspectJ binding code. For the benchmark numbers the join points advised by those advice were invoked 1,000,000 times. AspectJ 1.6.7: -`` - +[source, text] .... Manually fetching annotation with getAnnotation(): 645ms Binding annotation with @annotation(Marker): 445ms (was >20 *seconds* for 1.6.6, due to an extra reflection call) diff --git a/docs/dist/doc/README-168.adoc b/docs/dist/doc/README-168.adoc index eee958509..0a8e3cbb8 100644 --- a/docs/dist/doc/README-168.adoc +++ b/docs/dist/doc/README-168.adoc @@ -25,12 +25,11 @@ that is not These three meet that spec: -`` - +[source, xml] .... - <include within="*"/> - <include within="@Foo *"/> - <exclude within="*Funk*y*"/> +<include within="*"/> +<include within="@Foo *"/> +<exclude within="*Funk*y*"/> .... The include="*" can be optimized. The include="@Foo *" is not optimized. @@ -51,22 +50,21 @@ more frequently. The stack trace when this is hit looks like: -`` - +[source, text] .... - ... - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) - at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) - ... +... +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:427) +at org.aspectj.weaver.ReferenceType.isAssignableFrom(ReferenceType.java:393) +... .... The weaver has changed over the 1.5 and 1.6 releases and is now reaching diff --git a/docs/dist/doc/README-169.adoc b/docs/dist/doc/README-169.adoc index 1df44489f..4921f23d4 100644 --- a/docs/dist/doc/README-169.adoc +++ b/docs/dist/doc/README-169.adoc @@ -14,6 +14,7 @@ declare annotation constructs that take a member signature. For example, if you wanted to attach an annotation to all your getter like methods, you needed two constructs +[source, java] .... declare @method: * is*(): @FooBar; declare @method: * get*(): @FooBar; @@ -22,6 +23,7 @@ declare @method: * get*(): @FooBar; Now AspectJ allows compound patterns for declare @method/@constructor/@field. +[source, java] .... declare @method: (* is*()) || (* get*()): @FooBar; .... @@ -32,6 +34,7 @@ It is now possible to ITD member types. The syntax is as would be expected. This example introduces a new member type called Inner into type Foo: +[source, java] .... public class Foo { public static void main(String[] args) { @@ -71,10 +74,9 @@ within it to switch-off if there is nothing for them to do. Here is an example, 'AspectA' will switch itself off if the type 'a.b.c.Anno' cannot be found: -`` - +[source, xml] .... - <aspect name="AspectA" requires="a.b.c.Anno"/> +<aspect name="AspectA" requires="a.b.c.Anno"/> .... ==== Reduction in class file sizes: https://bugs.eclipse.org/bugs/show_bug.cgi?id=312839[312839] @@ -130,8 +132,7 @@ the pointcuts defined in the original aspect. Here is an example: -`` - +[source, xml] .... <aspectj> <aspects> @@ -154,8 +155,7 @@ specifies that Y should in fact only be applied to com.foo..* types. It is now possible to use joinpoint context in the messages attached to declare warning and declare error constructs. Some examples: -`` - +[source, java] .... declare warning: execution(* A.m(..)): "joinpoint is {joinpoint}"; declare warning: execution(* A.m(..)): "joinpoint kind is '{joinpoint.kind}'"; @@ -178,8 +178,7 @@ the message. Please raise an enhancement request if you need other keys It is now possible to use a type pattern with declare warning and declare error. For example: -`` - +[source, java] .... declare warning: I+ && !hasfield(int i): "Implementations of I are expected to have a int field called i"; .... @@ -190,8 +189,7 @@ This is the ability to narrow the types of interest so that interfaces can be ignored, or inner types, or classes or aspects. There is now a new is() construct that enables this: -`` - +[source, java] .... execution(* (!is(InnerType)).m(..)) {} !within(* && is(InnerType)) {} @@ -202,8 +200,9 @@ InnerType, AnonymousType, EnumType, AnonymousType. Note: It is important to understand that "!within(is(InnerType))" and "within(!is(InnerType))" are not the same. The latter one is unlikely to -be what you want to use. For example here: `` +be what you want to use. For example here: +[source, java] .... class Boo { void foo() {} @@ -223,8 +222,7 @@ result of that match will be negated. Some users always expect this: -`` - +[source, java] .... class C { } @@ -248,8 +246,7 @@ produce slightly different output. Here is the output of javap when that is built with 1.6.8: -`` - +[source, java] .... class C extends java.lang.Object{ public int ajc$interField$X$someField; @@ -259,8 +256,7 @@ class C extends java.lang.Object{ Here is the output of javap when that is built with 1.6.9: -`` - +[source, java] .... class C extends java.lang.Object{ private int someField; @@ -284,8 +280,7 @@ and if you browse to it you will see it currently contains 1.6.9 dev builds under the name 1.6.9.BUILD-SNAPSHOT. The repo is added with this magic: -`` - +[source, xml] .... <repository> <id>maven.springframework.org</id> diff --git a/docs/dist/doc/README-170.adoc b/docs/dist/doc/README-170.adoc index de0248de7..b76f56139 100644 --- a/docs/dist/doc/README-170.adoc +++ b/docs/dist/doc/README-170.adoc @@ -36,6 +36,7 @@ start of a system using LTW and then reuses that woven bytecode on subsequent starts - this saves weaving time and also memory consumption. To activate it, use the following system properties: +[source, text] .... -Daj.weaving.cache.enabled=true -Daj.weaving.cache.dir=/tmp/aspectj-cache/ @@ -51,8 +52,9 @@ Eclipse compiler. It means that you can now use the new Java 7 language constructs in your programs: -- Diamond operator in advice: `` +- Diamond operator in advice: +[source, java] .... aspect Foo { before(): execution(* *(..)) { @@ -61,58 +63,63 @@ aspect Foo { } .... -- Diamond operator in ITD: `` +- Diamond operator in ITD: +[source, java] .... public List DiamondITD.ls = new ArrayList<>(); .... -- Underscore literals and binary literals in advice: `` +- Underscore literals and binary literals in advice: +[source, java] .... - before(): execution(* *(..)) { - int onemill = 1_000_000; - int four =0b100; - } +before(): execution(* *(..)) { + int onemill = 1_000_000; + int four =0b100; +} .... - Multi-catch:`` +[source, java] .... before(): execution(* main(..)) { - try { - foo("abc"); - } catch (ExceptionA | ExceptionB ex) { - bar(ex); - } + try { + foo("abc"); + } catch (ExceptionA | ExceptionB ex) { + bar(ex); + } } .... - String switch:`` +[source, java] .... - before(String s): execution(* *(..)) && args(s) { - switch(s) { - case "quux": - foo(); - break; - case "bar": - foo(); - break; - default: - foo(); - break; - } - } +before(String s): execution(* *(..)) && args(s) { + switch(s) { + case "quux": + foo(); + break; + case "bar": + foo(); + break; + default: + foo(); + break; + } +} .... - Try with resources:`` +[source, java] .... - try ( - InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dest)) - { - // code - } +try ( + InputStream in = new FileInputStream(src); + OutputStream out = new FileOutputStream(dest)) +{ + // code +} .... diff --git a/docs/dist/doc/README-174.adoc b/docs/dist/doc/README-174.adoc index 7b4cbb54c..3b55b4a43 100644 --- a/docs/dist/doc/README-174.adoc +++ b/docs/dist/doc/README-174.adoc @@ -18,6 +18,7 @@ JVM where JMX is turned on (https://bugs.eclipse.org/bugs/show_bug.cgi?id=420210[420210]) The new keys are: + +[source, java] .... joinpoint.enclosingclass // Bar joinpoint.enclosingmember // void Bar.foo(String) @@ -29,6 +30,7 @@ All keys are case insensitive. needing to supply a file (https://bugs.eclipse.org/bugs/show_bug.cgi?id=419279[419279]) + +[source, text] .... ajc -Xlint:adviceDidNotMatch=error,noGuardForLazyTjp=ignore Foo.java .... diff --git a/docs/dist/doc/README-180.adoc b/docs/dist/doc/README-180.adoc index fe988aa5a..115de3d6d 100644 --- a/docs/dist/doc/README-180.adoc +++ b/docs/dist/doc/README-180.adoc @@ -21,8 +21,9 @@ patch on top of Eclipse 4.3.2). Here is a sample AspectJ8 program: +[source, java] .... -=== 8< ==== C.java ==== 8< === +// === 8< ==== C.java ==== 8< === import java.util.Arrays; interface I { @@ -67,5 +68,5 @@ class MyClass { return args; } } -=== 8< ==== C.java ==== 8< === +// === 8< ==== C.java ==== 8< === .... diff --git a/docs/dist/doc/README-182.adoc b/docs/dist/doc/README-182.adoc index 45215367d..28fa7b2da 100644 --- a/docs/dist/doc/README-182.adoc +++ b/docs/dist/doc/README-182.adoc @@ -35,8 +35,7 @@ Here is a short example, a very basic annotation and application: ===== Marker.java -`` - +[source, java] .... import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -47,8 +46,7 @@ public @interface Marker { } ===== Code.java -`` - +[source, java] .... public class Code { @@ -60,13 +58,13 @@ public class Code { } public void moo() {} - + @Marker public void boo() {} - + @Marker public void too() {} - + public void woo() {} } .... @@ -78,8 +76,7 @@ contrived demo!) ===== DemoProcessor.java -`` - +[source, java] .... import java.io.*; import javax.tools.*; @@ -90,7 +87,7 @@ import javax.lang.model.element.*; @SupportedAnnotationTypes(value= {"*"}) @SupportedSourceVersion(SourceVersion.RELEASE_6) -public class DemoProcessor extends AbstractProcessor { +public class DemoProcessor extends AbstractProcessor { private Filer filer; @@ -106,7 +103,7 @@ public class DemoProcessor extends AbstractProcessor { if (element.getKind() == ElementKind.METHOD) { // For any methods we find, create an aspect: String methodName = element.getSimpleName().toString(); - String aspectText = + String aspectText = "public aspect Advise_"+methodName+" {\n"+ " before(): execution(* "+methodName+"(..)) {\n"+ " System.out.println(\""+methodName+" running\");\n"+ @@ -131,22 +128,19 @@ public class DemoProcessor extends AbstractProcessor { With those sources, we compile the processor: -`` - +[source, text] .... ajc -1.6 DemoProcessor.java Marker.java .... Now compile the code with the processor specified: -`` - +[source, text] .... ajc -1.6 -processor DemoProcessor -showWeaveInfo Code.java Marker.java .... -`` - +[source, text] .... Generated aspect to advise too Generated aspect to advise boo @@ -159,8 +153,7 @@ the code being compiled immediately. Finally we can run it: -`` - +[source, text] .... java Code boo running diff --git a/docs/dist/doc/README-183.adoc b/docs/dist/doc/README-183.adoc index 95425e392..8c615ef84 100644 --- a/docs/dist/doc/README-183.adoc +++ b/docs/dist/doc/README-183.adoc @@ -35,6 +35,7 @@ extraneous dependencies to an applications build classpath. Example: +[source, java] .... import org.aspectj.lang.annotation.*; @@ -63,6 +64,7 @@ appears to come up when the aspect is non-optimal anyway and hitting preinitialization was never really intended by the pointcut writer. For example: +[source, java] .... execution(* foo(..)) && cflow(within(Bar)) .... @@ -72,12 +74,14 @@ joinpoints, many of which the user probably didn't mean to. It feels like we actually need a warning to indicate the pointcut is probably suboptimal. What the user probably meant was something more like this: +[source, java] .... execution(* foo(..)) && cflow(execution(* Bar.*(..)) .... or +[source, java] .... execution(* foo(..)) && cflow(within(Bar) && execution(* *(..))) .... diff --git a/docs/dist/doc/README-187.adoc b/docs/dist/doc/README-187.adoc index de61a362b..bcc5f75cc 100644 --- a/docs/dist/doc/README-187.adoc +++ b/docs/dist/doc/README-187.adoc @@ -25,8 +25,7 @@ will not be woven. Here is a simple aspect: -`` - +[source, java] .... public aspect Azpect { before(): execution(* *(..)) { @@ -37,8 +36,7 @@ public aspect Azpect { Compiled via: -`` - +[source, text] .... ajc -1.8 Azpect.java -outxml .... @@ -48,8 +46,7 @@ META-INF/aop-ajc.xml. I then have this sample application (same directory): -`` - +[source, java] .... import java.lang.management.ManagementFactory; import org.aspectj.weaver.loadtime.Agent; @@ -96,8 +93,7 @@ public class Application { And this Sample class: -`` - +[source, java] .... public class Sample { public void doSomething() { @@ -116,8 +112,7 @@ JDK tools.jar on your classpath*. Once compiled we can run it: -`` - +[source, text] .... java -DAGENT_PATH=<path-to>/aspectjweaver.jar Application .... diff --git a/docs/dist/doc/README-190.adoc b/docs/dist/doc/README-190.adoc index 3b1f27784..323573146 100644 --- a/docs/dist/doc/README-190.adoc +++ b/docs/dist/doc/README-190.adoc @@ -41,6 +41,7 @@ In anticipation of not all build plugins supporting that -Xajruntimetarget option, you can now specify these kinds of option in the ASPECTJ_OPTS environment variable. Set that in your environment: +[source, text] .... export ASPECTJ_OPTS="-Xajruntimetarget:1.9" .... @@ -58,17 +59,18 @@ useful with Java9 which includes a number of module related commands. For example, here is an iajc usage with compilerArg that is passing --add-modules java.xml.bind: +[source, xml] .... - <iajc destdir="bin" failonerror="true" - showWeaveInfo="true" source="1.9" target="1.9" - debug="true" fork="true" maxmem="256m"> - <compilerArg value="--add-modules"/> - <compilerArg value="java.xml.bind"/> - <src path="src" /> - <classpath> - <pathelement location="${aspectj.home}/lib/aspectjrt.jar"/> - </classpath> - </iajc> +<iajc destdir="bin" failonerror="true" + showWeaveInfo="true" source="1.9" target="1.9" + debug="true" fork="true" maxmem="256m"> + <compilerArg value="--add-modules"/> + <compilerArg value="java.xml.bind"/> + <src path="src" /> + <classpath> + <pathelement location="${aspectj.home}/lib/aspectjrt.jar"/> + </classpath> +</iajc> .... 1.9.0.RC4 available 21-Feb-2018 @@ -103,6 +105,7 @@ AspectJ can now be used with the new module system available in Java9. The key jars in AspectJ have been given automatic module names. The automatic module name is org.aspectj.runtime for the aspectjrt module: +[source, text] .... $ java --module-path <pathto>/lib/aspectjrt.jar --list-modules | grep aspectj @@ -112,6 +115,7 @@ org.aspectj.runtime file:///<pathto>/lib/aspectjrt.jar automatic And similarly org.aspectj.weaver and org.aspectj.tools for aspectjweaver and aspectjtools respectively: +[source, text] .... $ java --module-path <pathto>/lib/aspectjweaver.jar --describe-module org.aspectj.weaver @@ -137,6 +141,7 @@ contains org.aspectj.asm.internal AspectJ understands module-info.java source files and building modules that include aspects. Here is an example: +[source, java] .... module-info.java @@ -170,6 +175,7 @@ public aspect Azpect { We can now build those into a module: +[source, text] .... $ ajc -1.9 module-info.java otherpkg/Azpect.java pkg/Demo.java -outjar demo.jar @@ -182,12 +188,14 @@ Wait, that failed! Yes, aspectjrt.jar (which includes the required org.aspectj.weaver module) wasn't supplied. We need to pass it on the module-path: +[source, text] .... $ ajc -1.9 --module-path <pathto>/aspectjrt.jar module-info.java otherpkg/Azpect.java pkg/Demo.java -outjar demo.jar .... Now we have a demo module we can run: +[source, text] .... $ java --module-path <pathto>/aspectjrt.jar:demo.jar --module demo/pkg.Demo @@ -206,8 +214,9 @@ A module is really just a jar with a module-info descriptor. As such you can simply pass a module on the inpath and binary weave it with other aspects. Take the module we built above, let's weave into it again: +[source, java] .... -extra/AnotherAzpect.java +// extra/AnotherAzpect.java package extra; @@ -218,6 +227,7 @@ public aspect AnotherAzpect { } .... +[source, text] .... $ ajc -inpath demo.jar AnotherAzpect.java -outjar newdemo.jar .... @@ -231,6 +241,7 @@ Because the new jar produced includes the compiled aspect, the module-info specification inside is still correct, so we can run it exactly as before: +[source, text] .... $ java --module-path ~/installs/aspectj190rc1/lib/aspectjrt.jar:newdemo.jar --module demo/pkg.Demo @@ -239,9 +250,6 @@ AnotherAzpect running Demo running .... - + - + - === Faster Spring AOP Dave Syer recently created a series of benchmarks for checking the speed @@ -250,6 +258,7 @@ of Spring-AspectJ: https://github.com/dsyer/spring-boot-aspectj Here we can see the numbers for AspectJ 1.8.11 (on an older Macbook Pro): +[source, text] .... Benchmark (scale) Mode Cnt Score Error Units StartupBenchmark.ltw N/A avgt 10 2.553 ~ 0.030 s/op @@ -295,6 +304,7 @@ primary change is factoring in the annotation type. What difference does that make? AspectJ 1.9.0.RC1: +[source, text] .... Benchmark (scale) Mode Cnt Score Error Units StartupBenchmark.ltw N/A avgt 10 2.568 ~ 0.035 s/op diff --git a/docs/dist/doc/README-191.adoc b/docs/dist/doc/README-191.adoc index acab550c3..bba435893 100644 --- a/docs/dist/doc/README-191.adoc +++ b/docs/dist/doc/README-191.adoc @@ -14,6 +14,7 @@ AspectJ has updated to a recent JDT compiler version (commit This means you can use the 'var' support. A simple example of combining var with an aspect: +[source, java] .... public class Code3 { public static void main(String []argv) { diff --git a/docs/dist/doc/README-193.adoc b/docs/dist/doc/README-193.adoc index a75724c2c..22824b66b 100644 --- a/docs/dist/doc/README-193.adoc +++ b/docs/dist/doc/README-193.adoc @@ -10,8 +10,9 @@ expression syntax, but you must activate support for that via an --enable-preview flag when using the compiler and attempting to run the resultant classes: Here is Switch3.java: +[source, java] .... -=========8<========= +// =========8<========= public class Switch3 { public static void main(String[] argv) { System.out.println(one(Color.R)); @@ -29,7 +30,7 @@ public class Switch3 { }; return result; } - + public static final int foo(int i) { return i+1; } @@ -44,11 +45,12 @@ aspect X { return proceed()*3; } } -=========8<========= +// =========8<========= .... Compile it with: +[source, text] .... $ ajc --enable-preview -showWeaveInfo -12 Switch3.java @@ -63,6 +65,7 @@ Join point 'method-call(int Switch3.foo(int))' in Type 'Switch3' (Switch3.java:1 Now run it: +[source, text] .... $ java --enable-preview Switch3 3 diff --git a/docs/dist/doc/README-195.adoc b/docs/dist/doc/README-195.adoc index 2af7e42a7..36a157c53 100644 --- a/docs/dist/doc/README-195.adoc +++ b/docs/dist/doc/README-195.adoc @@ -12,8 +12,9 @@ must activate support for that via an --enable-preview flag when using the compiler and attempting to run the resultant classes: Here is Code.java: +[source, java] .... -=======8<========= +// =======8<========= public class Code { public static void main(String[] argv) { } @@ -33,17 +34,19 @@ lines } } -=========8<========= +// =========8<========= .... Compile it with: +[source, text] .... $ ajc --enable-preview -13 Code.java .... Now run it: +[source, text] .... $ java --enable-preview Code This diff --git a/docs/dist/doc/README-196.adoc b/docs/dist/doc/README-196.adoc index 536cd4ec9..35e7ab2d3 100644 --- a/docs/dist/doc/README-196.adoc +++ b/docs/dist/doc/README-196.adoc @@ -11,12 +11,13 @@ AspectJ 1.9.6 supports Java14. Java14 introduces records, but you must activate support for that via an --enable-preview flag when using the compiler and attempting to run the resultant classes: Here is Code.java: +[source, java] .... -=======8<========= +// =======8<========= public record Person(String firstName, String lastName, int age) {} -=======8<========= +// =======8<========= -=======8<========= +// =======8<========= public class UsingPersonRecord { public static void main(String[] argv) { Person p = new Person("A","B",99); @@ -24,25 +25,27 @@ public class UsingPersonRecord { System.out.println(p.firstName()); } } -=======8<========= +// =======8<========= -=======8<========= +// =======8<========= public aspect TraceRecordComponents { before(): execution(public * *()) { System.out.println(thisJoinPointStaticPart); } } -=======8<========= +// =======8<========= .... Compile it with: +[source, text] .... $ ajc --enable-preview -14 Person.java UsingPersonRecord.java TraceRecordComponents.java .... Now run it: +[source, text] .... $ java --enable-preview UsingPersonRecord execution(String Person.toString()) diff --git a/docs/dist/doc/changes.adoc b/docs/dist/doc/changes.adoc index c7b2d6975..25ef37f09 100644 --- a/docs/dist/doc/changes.adoc +++ b/docs/dist/doc/changes.adoc @@ -178,10 +178,10 @@ compiler supports an additional option, -showWeaveInfo, which will produce informational messages concerning the activity of the weaver. For example: + +[source, text] .... - Type 'tjp.Demo' (Demo.java:30) advised by around advice from 'tjp.GetInfo' - (GetInfo.java:26) [RuntimeTest=true] - +Type 'tjp.Demo' (Demo.java:30) advised by around advice from 'tjp.GetInfo' +(GetInfo.java:26) [RuntimeTest=true] .... * https://bugs.eclipse.org/bugs/show_bug.cgi?id=44191[44191] AspectJ 1.2.1 improves the error messages issued in many of the infamous "can't diff --git a/docs/dist/doc/porting.adoc b/docs/dist/doc/porting.adoc index bc95dc5c7..cbf8ede6d 100644 --- a/docs/dist/doc/porting.adoc +++ b/docs/dist/doc/porting.adoc @@ -37,35 +37,36 @@ The following example program illustrates the differences in join point matching with the `call` pointcut designator between 1.4 and 1.3 compliance levels. -.... -01 class A { -02 public void doIt() {...}; -03 } -04 -05 class B extends A { -06 public void doThisToo() {...}; -07 } -08 -09 -10 public class CallsAandB { -11 -12 public static void main(String[] args) { -13 B b = new B(); -14 A bInDisguise = new B(); -15 -16 b.doIt(); // AspectJ 1.2 matches here -17 bInDisguise.doIt(); // this is never matched -18 } -19 -20 } -21 -22 aspect CallPCDMatchingExample { -23 -24 before() : call(* B.doIt(..)) { -25 System.out.println("About to call B.doIt(...)"); -26 } -27 -28 } +[source, java] +.... +/*01*/ class A { +/*02*/ public void doIt() {...}; +/*03*/ } +/*04*/ +/*05*/ class B extends A { +/*06*/ public void doThisToo() {...}; +/*07*/ } +/*08*/ +/*09*/ +/*10*/ public class CallsAandB { +/*11*/ +/*12*/ public static void main(String[] args) { +/*13*/ B b = new B(); +/*14*/ A bInDisguise = new B(); +/*15*/ +/*16*/ b.doIt(); // AspectJ 1.2 matches here +/*17*/ bInDisguise.doIt(); // this is never matched +/*18*/ } +/*19*/ +/*20*/ } +/*21*/ +/*22*/ aspect CallPCDMatchingExample { +/*23*/ +/*24*/ before() : call(* B.doIt(..)) { +/*25*/ System.out.println("About to call B.doIt(...)"); +/*26*/ } +/*27*/ +/*28*/ } .... When this program is compiled with AspectJ 1.2 using the default @@ -99,8 +100,8 @@ does not match at a join point, and a user may have expected it to. Compiling the above program using AspectJ 1.2 produces the following compiler output: +[source, text] .... - CallsAandB.java:24 warning does not match because declaring type is A, if match desired use target(B) [Xlint:unmatchedSuperTypeInCall] before() : call(* B.doIt(..)) { ^^^^^^^^^^^^^^^ @@ -109,7 +110,6 @@ before() : call(* B.doIt(..)) { 1 warning - .... The warning is telling us that the call pointcut associated with the @@ -147,6 +147,7 @@ an interface is now (correctly) prohibited, and there will no longer be a constructor-execution join point for the interface. To initialize a field declared on an interface, use initialization, e.g., +[source, java] .... int I.i; after(I i) returning: initialization(I) && this(i) { i.i = 2; } @@ -154,6 +155,7 @@ after(I i) returning: initialization(I) && this(i) { i.i = 2; } To pick out the constructor-execution for any implementation of I, try +[source, java] .... execution(I+.new(..)) .... @@ -172,6 +174,7 @@ older version of BCEL available earlier on your classpath than the version included in the 1.2 aspectjtools.jar then you will see errors like: +[source, text] .... C:\work\test\TestAspect.aj error Internal compiler error java.lang.NoSuchMethodError: org.apache.bcel.generic.InstructionFactory. @@ -219,6 +222,7 @@ Conflicts will be reported for no-argument constructors generated by compilers when no constructor is defined for a class. That means the following code will compile in 1.0 but not in 1.1: +[source, java] .... class C {} aspect A { @@ -243,6 +247,7 @@ The compiler will report an error that the form `aspect {name} dominates {list}...` is no longer supported. It has been replaced by a new declare statement: +[source, java] .... declare precedence : {name} {list}... .... @@ -269,6 +274,7 @@ returning advice. The main change that was made was of after returning advice for constructor execution join points. Previously, this advice was legal: +[source, java] .... after() returning (Foo f): execution(Foo.new(..)) { ... } .... @@ -280,6 +286,7 @@ constructor calls) do not return the value of the new object. Rather, void method. With that in mind, any code like the above should be conveted to the form. +[source, java] .... after(Foo f) returning: this(f) && execution(Foo.new(..)) { ... } .... @@ -287,6 +294,7 @@ after(Foo f) returning: this(f) && execution(Foo.new(..)) { ... } In compilers prior to 1.0.4, the following advice could pick out join points +[source, java] .... after() returning (String s): call(void foo()) { ... } .... @@ -294,6 +302,7 @@ after() returning (String s): call(void foo()) { ... } This is no longer picked out. This pattern was most commonly used in highly polymorphic contexts, such as +[source, java] .... after() returning (String s): call(* foo()) { ... } .... @@ -301,6 +310,7 @@ after() returning (String s): call(* foo()) { ... } If you want to capture all calls, binding null objects for those that would otherwise have no value, you must use the `Object` type. +[source, java] .... after() returning (Object o): call(* foo()) { ... } .... @@ -378,18 +388,20 @@ for example, you named a parameter of a pointcut "set", you should (for your own sanity -- the compiler doesn't require it) rename it in the rewritten pointcut. +[source, java] .... pointcut sort(Collection set): calls(void addAll(set)); -==> +// ==> pointcut sort(Collection mySet): call(void addAll(mySet)); .... While converting to use singular nouns for the primitive pointcuts, you may also want to remove the "s" from your user-defined pointcuts. +[source, java] .... pointcut publicCalls(): calls(public * *(..)); -==> +// ==> pointcut publicCall(): call(public * *(..)); .... @@ -412,9 +424,10 @@ straightforward, depending on whether the pointcut exposed state or not. Receptions pointcuts that did not expose state can simply be replaced by the new `call` and `target` pointcuts: +[source, java] .... receptions(void Foo.m()) -==> +// ==> target(Foo) && call(void m()) .... @@ -424,9 +437,10 @@ Some receptions pointcuts exposed the receiving object by replacing the receiving type with a pointcut formal. These PCDs should be rewritten to use the new `target` pointcut to expose the receiving object. +[source, java] .... pointcut fooCallees(Foo f): receptions(void f.m()); -==> +// ==> pointcut fooCallee(Foo f): target(f) && call(void m()); .... @@ -434,9 +448,10 @@ Like xref:#_1_0a1-fixing-state-access[other pointcuts], receptions pointcuts that exposed one or more arguments should be rewritten to use the `args` pointcut: +[source, java] .... pointcut intPassers(int i, int j): receptions(void Foo.m(i, j)); -==> +// ==> pointcut intPasser(int i, int j): args(i, j) && target(Foo) && call(void m(int, int)); .... @@ -453,9 +468,10 @@ but also of classes that extended C. If you want this behaviour, then you need to use the new subtypes operator, +, on the type name in question. So, +[source, java] .... receptions(C.new()) -==> +// ==> call(C+.new()) .... @@ -468,6 +484,7 @@ allow all kinds of advice it may be that the object isn't constructed yet (say, in before or around advice). This is a benefit, in that it allows caching constructed objects +[source, java] .... aspect Singleton { private C theC = null; @@ -482,9 +499,10 @@ aspect Singleton { but it does require some rewriting. The new object can be accessed as the return value in after returning advice. So, +[source, java] .... after(Point p) returning (): receptions(p.new(int, int)) { ... } -==> +// ==> after() returning (Point p): call(Point+.new(int, int)) { ... } .... @@ -509,15 +527,17 @@ Any time you have a pointcut that has a signature where one of the arguments was a pointcut or advice formal, just replace that formal with its type and add an `args` pointcut. +[source, java] .... pointcut intPassers(int i, int j): calls(void Foo.m(i, j)); -==> +// ==> pointcut intPasser(int i, int j): args(i, j) && call(void Foo.m(int, int)); .... +[source, java] .... pointcut stringPassers(String s): receptions(void Foo.m(s, ..)); -==> +// ==> pointcut stringPasser(String s): args(s, ..) && call(void Foo.m(String, ..)); .... @@ -525,6 +545,7 @@ pointcut stringPasser(String s): args(s, ..) && call(void Foo.m(String, ..)); If a calls pointcut exposed the the receiving object, such as +[source, java] .... pointcut fooCallees(Foo f): calls(void f.m()); .... @@ -532,6 +553,7 @@ pointcut fooCallees(Foo f): calls(void f.m()); then the new version should use the `target` pointcut to get at that object +[source, java] .... pointcut fooCallee(Foo f): target(f) && call(void Foo.m()); .... @@ -543,9 +565,10 @@ returning advice, when it is guaranteed that the object was successfully constructed. So instead of using the `target` pointcut to expose the value, you should use the normal `after returning` mechanism: +[source, java] .... after(Point p) returning (): calls(p.new(int, int)) { ... } -==> +// ==> after() returning (Point p): call(Point+.new(int, int)) { ... } .... @@ -555,15 +578,17 @@ Exposing the target object of a `gets` or `sets` pointcut should be done the same way it was for `calls` pointcuts, with the new `target` pointcut. +[source, java] .... before(Frame f): gets(Color f.color) { ... } -==> +// ==> before(Frame f): target(f) && get(Color Frame.color) { ... } .... +[source, java] .... before(Frame f): sets(Color f.color) { ... } -==> +// ==> before(Frame f): target(f) && set(Color Frame.color) { ... } .... @@ -573,11 +598,14 @@ the field yourself in the body. Depending on the rest of your system, you may need to restrict the advice from the aspect body to eliminiate the circularity. +[source, java] .... aspect A { before(Frame f, Color c): gets(Color f.color)[c] { ... } } -==> + +// ==> + aspect A { before(Frame f): target(f) && get(Color Frame.color) && !within(A) { @@ -590,11 +618,14 @@ aspect A { The same can be done for `around` advice. However, the only way to port after advice that needs the old value is to convert it to around advice. +[source, java] .... aspect A { after(Frame f, Color c) returning (): gets(Color f.color)[c] { ... } } -==> + +// ==> + aspect A { void around(Frame f): target(f) && get(Color Frame.color) && !within(A) { @@ -610,9 +641,10 @@ available, but not the way it was previously. Instead of using the square bracket syntax, we use an `args` pointcut. All set join points are assumed to have exactly one argument, which holds the new value. So, +[source, java] .... after(Color newColor): sets(Color Frame.color)[][newColor] { ... } -==> +// ==> after(Color newColor): args(newColor) && set(Color Frame.color) { ... } .... @@ -625,9 +657,10 @@ The value of the exception at an exception handler join point is now accessed through the `args` pointcut; all exception handler join points are treated as having exactly one argument, the exception value. So, +[source, java] .... before(NotFoundException e): handlers(e) { ... } -==> +// ==> before(NotFoundException e): args(e) && handler(NotFoundException) { ... } .... @@ -640,9 +673,10 @@ closed, and within can only take type patterns, not pointcut or advice formals. A use of the `this` pointcut will capture what previous implementations did: +[source, java] .... pointcut usesFoo(Foo f): within(f); -==> +// ==> pointcut usesFoo(Foo f): this(f) && within(Foo); .... @@ -667,6 +701,7 @@ to match. For example, the pointcut +[source, java] .... calls(void m(Object)) .... @@ -677,6 +712,7 @@ out method calls to methods that are defined to take exactly the type Object, which may be a lot fewer join points. If you want the old behaviour, simply convert to +[source, java] .... call(void m(Object+)) .... @@ -692,10 +728,11 @@ pointcut, composed (with `&&`) with another pointcut. If the other pointcut was a `receptions` pointcut, then `instanceof` should be converted to `target` (and `receptions` converted to `call`). So, +[source, java] .... pointcut stateChanges(Subject s): instanceof(s) && receptions(void Button.click()); -==> +// ==> pointcut stateChange(Subject s): target(s) && call(void Button.click()); .... @@ -703,15 +740,17 @@ pointcut stateChange(Subject s): In all other cases, `instanceof` referred to the currently executing object, and so should be converted into `this` +[source, java] .... before(Point p): instanceof(p) && executions(* makePolar(..)) { ... } -==> +// ==> before(Point p): this(p) && execution(* makePolar(..)) { ... } .... +[source, java] .... pointcut setup(Client c): instanceof(c) && calls(Remote Naming.lookup(String)); -==> +// ==> pointcut setup(Client c): this(c) && calls(Remote Naming.lookup(String)); .... @@ -728,9 +767,10 @@ fields. The old behaviour can be recovered with a simple rewrite. +[source, java] .... initializations(A) -==> +// ==> initialization(A.new(..)) && !execution(A.new(..)) .... @@ -760,20 +800,22 @@ If the aspect whose presense you are checking for was defined `of eachcflow`, `of eachcflowbelow`, or, more unlikely, `of eachJVM()`, then the conversion is simple: +[source, java] .... hasaspect(A) -==> +// ==> if(A.hasAspect()) .... If the aspect was defined `of eachobject`, then you will have to expose the current object in your pointcut or advice parameters: +[source, java] .... pointcut cut(): hasaspect(A) ... ; -==> +// ==> pointcut cut(Object o): this(o) && if(A.hasAspect(o)) ... ; -or +// or pointcut cut(Object o): target(o) && if(A.hasAspect(o)) ... ; .... @@ -782,11 +824,12 @@ aspect, then you can get the same state by using `A.aspectOf()` in the body of the advice. For example, if the aspect A were defined `of eachcflow`, then +[source, java] .... before(A myA): hasaspect(myA) { myA.checkStatus(); } -==> +// ==> before(): if(A.hasAspect()) { A myA = A.aspectOf(); myA.checkStatus(); @@ -801,9 +844,10 @@ of within and the xref:#_1_0a1-subtypes-to-plus[new subtypes operator], +, instead. You'll save two characters and be using a simpler and more orthogonal language. +[source, java] .... withinall(Foo) -==> +// ==> within(Foo+) .... @@ -813,9 +857,10 @@ within(Foo+) The returns keyword is no longer necessary for user-defined pointcuts. Simply remove it when you find it. +[source, java] .... pointcut publicIntCalls() returns int: calls(public int *(..)); -==> +// ==> pointcut publicIntCall(): call(public int *(..)); .... @@ -864,9 +909,10 @@ programs easier. There is one ugly idiom, however, that this change disposes of. If your program includes the type pattern `*..*`, which used to match all types, you can replace it with the much simpler *. +[source, java] .... pointcut unaryVoidMethods(): call(void *(*..*)); -==> +// ==> pointcut unaryVoidMethod(): call(void *(*)); .... @@ -882,11 +928,12 @@ wrote `subtypes(Foo)`, i.e., the subtypes of a single type, simply replace this with `Foo+`. Otherwise, use the + operator as appropriate in `TypePattern`. +[source, java] .... public void (subtypes(Target0 || Target1)).accept(Visitor v) { v.visit(this); } -==> +// ==> public void (Target0+ || Target1+).accept(Visitor v) { v.visit(this); } @@ -901,9 +948,10 @@ public void (Target0+ || Target1+).accept(Visitor v) { The returns keyword is no longer used for around advice. Instead, the return type is declared as it is for methods. So, +[source, java] .... around(Point p) returns void: setters(p) { ... } -==> +// ==> void around(Point p): setter(p) { ... } .... @@ -913,6 +961,7 @@ void around(Point p): setter(p) { ... } Around advice must now declare the checked exceptions it throws with a `throws` clause, much like a method. +[source, java] .... char around(char c) throws java.io.CharConversionException: converter(c) { char result; @@ -951,6 +1000,7 @@ This allows interesting advice interaction. In the following advice, for example, the `after throwing` advice will catch the exception thrown by the `before` advice +[source, java] .... aspect A { before(): call(void main(..)) { @@ -965,6 +1015,7 @@ aspect A { But reversing the order will give the `before` advice more precedence, making its exception uncatchable by the `after throwing` advice +[source, java] .... aspect A { after() throwing(RuntimeException e): call(void main(..)) { @@ -986,15 +1037,17 @@ If you use after returning advice and do not need to expose the return value, you no longer need to write an empty set of parentheses to indicate that fact. So, +[source, java] .... after(Formals) returning (): Pointcut { ... } -==> +// ==> after(Formals) returning: Pointcut { ... } .... The same syntax is now available for after throwing advice, in case you do not care what `Throwable` is thrown. +[source, java] .... after(Formals) throwing: Pointcut { ... } .... @@ -1013,6 +1066,7 @@ The `JoinPoint` object hierarchy has been folded into a single class, `org.aspectj.lang.JoinPoint`. A common pattern in logging, for example, was +[source, java] .... before() executions(* myMethod()) { ExecutionJoinPoint jp = (ExecutionJoinPoint)thisJoinPoint; @@ -1025,6 +1079,7 @@ before() executions(* myMethod()) { While there is still a rich hierarchy for signatures, there is only one `JoinPoint` type, so this can be rewritten as: +[source, java] .... before() executions(* myMethod()) { JoinPoint jp = thisJoinPoint; @@ -1045,12 +1100,14 @@ Some of the method names of `JoinPoint` have been reorganized, as well. The keywords `+implements` and `+extends` no longer exist. Instead, AspectJ uses the `declare` form for exactly the same functionality. +[source, java] .... Point +implements Serializable; => declare parents: Point implements Serializable; .... +[source, java] .... MyButton +extends ButtonAdaptor; => @@ -1063,6 +1120,7 @@ declare parents: MyButton extends ButtonAdaptor; Around advice advice no longer effects the static exception checking of Java. This means that the following code previously compiled: +[source, java] .... class C { void noExceptionDeclared() { @@ -1088,6 +1146,7 @@ exceptionDeclared() will not, actually, throw an exception, we now "soften" that exception, that is, take it out of the space of declared exceptions. +[source, java] .... declare soft: ExceptionType: Pointcut; .... @@ -1097,6 +1156,7 @@ would require runtime information. But picking out method calls is just fine. So in order to make the above example work, one new declaration is needed: +[source, java] .... declare soft: IOException: call(void C.exceptionDeclared()) && @@ -1109,9 +1169,10 @@ declare soft: IOException: The syntax of "of each" modifiers has changed. For `of eachcflow` and `of eachcflowbelow`, you can simply replace "of each" with "per". So, +[source, java] .... aspect A of eachcflow(...) { ... } -==> +// ==> aspect A percflow(...) { ... } .... @@ -1120,11 +1181,12 @@ remove that declaration entirely (because this is the default behaviour), or replace the `of eachJVM()` declaration with an `issingleton` declaration. +[source, java] .... aspect of eachJVM() { ... } -==> +// ==> aspect A { ... } -or +// or aspect A issingleton { ... } .... @@ -1135,13 +1197,16 @@ you replace with depends on the `Pointcut` you use. If you use a pointcut that picked out reception join points, then use `pertarget`, and rewrite the pointcut to pick out call join points. So +[source, java] .... aspect Shadow of eachobject(receptions(void Point.setX(int)) || receptions(void Point.setY(int))) { ... } -==> + +// ==> + aspect Shadow pertarget(call(void Point.setX(int)) || call(void Point.setY(int))) { ... @@ -1193,7 +1258,7 @@ In many cases, you may not care whether the points of `Pointcut` are included or not, and so can safely leave `cflow(Pointcut)` pointcut designators alone. However, if you use the idiom -[source,codeindent] +[source, java] ---- Pointcut && ! cflow(Pointcut) ---- @@ -1201,7 +1266,7 @@ Pointcut && ! cflow(Pointcut) to capture the non-recursive entries to a particular pointcut, you will definitely want to rewrite that as -[source,codeindent] +[source, java] ---- Pointcut && ! cflowbelow(Pointcut) ---- @@ -1212,14 +1277,14 @@ The primitive pointcut designator `cflowtop(Pointcut)` has been removed from the language, as it is expressible with `cflow` or `cflowbelow`. All uses of `cflowtop(Pointcut)` can be rewritten as: -[source,codeindent] +[source, java] ---- cflowbelow(Pointcut && ! cflowbelow(Pointcut)) ---- Though in most cases the following is sufficient -[source,codeindent] +[source, java] ---- cflow(Pointcut && ! cflowbelow(Pointcut)) ---- @@ -1232,7 +1297,7 @@ override all of its abstract pointcuts with an empty pointcut. AspectJ 0.8beta3 enforces the restriction that a concrete aspect may not have any abstract pointcuts. Thus the following extension: -[source,codeindent] +[source, java] ---- abstract aspect A { abstract pointcut pc(); @@ -1245,14 +1310,14 @@ will no longer compile. Adding the new empty pointcut designator -[source,codeindent] +[source, java] ---- pointcut Id(); ---- in the declaration of the concrete aspect fixes this problem. -[source,codeindent] +[source, java] ---- abstract aspect A { abstract pointcut pc(); @@ -1269,7 +1334,7 @@ aspect B { Previously, the compiler silently refrained from applying a piece of advice to join points within its own advice body. So, for example, in -[source,codeindent] +[source, java] ---- class C { static int i; @@ -1292,7 +1357,7 @@ Most cases of this error can be fixed by correctly specifying the desired pointcut: In the above example, the intention is clearly not to trace _all_ references of `C.i`, just those outside the aspect. -[source,codeindent] +[source, java] ---- class C { static int i; @@ -1310,7 +1375,7 @@ code in the aspect, but not in the particular piece of advice. In such cases, you can pull the body of the advice into a method and restrict away from that method (and away from calls to that method): -[source,codeindent] +[source, java] ---- class C { static int i; @@ -1353,10 +1418,10 @@ to the 0.8beta1 release of AspectJ. The syntax of introduction has changed. Porting most programs should require some simple editing. Anywhere you have an introduction block -[source,codeindent] +[source, java] ---- introduction GTN { - ... + // ... } ---- @@ -1368,7 +1433,7 @@ For field introduction, place the `GTN` in front of the field name, and for constructor introduction, place the `GTN` in front of the `new` identifier. -[source,codeindent] +[source, java] ---- introduction Foo { public void doStuff() { this.doStuffLater(); } @@ -1376,7 +1441,7 @@ introduction Foo { public new(int x) { super(); calorieCount = x; } } -==> +// ==> public void Foo.doStuff() { this.doStuffLater(); } public int Foo.calorieCount= 3; @@ -1387,14 +1452,14 @@ For implements and extends introduction, move the `GTN` in front of the new identifiers `implements` or `extends`, and place that in a `declare parents` form. -[source,codeindent] +[source, java] ---- introduction Foo { implements Comparable; extends Goo; } -==> +// ==> declare parents: Foo implements Comparable; declare parents: Foo extends Goo; @@ -1404,13 +1469,13 @@ In all cases, if the `GTN` is just a type name, it can be moved down on its own. However, if the `GTN` uses any of `&&`, `||`, and `!`, it must be parenthesized. -[source,codeindent] +[source, java] ---- introduction subtypes(Foo) && !Goo { int x; } -==> +// ==> int (Foo+ && !Goo).x; ---- @@ -1423,7 +1488,7 @@ need to modify your code to avoid this accessibility issue, or you will need to use the `privileged` modifier on the aspect that contains the introduction. -[source,codeindent] +[source, java] ---- class Counter { private int count = 2; @@ -1435,7 +1500,8 @@ aspect ExposeCountersPrivates { } } -==> +// ==> + // in 0.8, only privileged aspects can expose a class's privates privileged aspect ExposeCountersPrivates { public int Counter.getCount() { return count; } @@ -1446,7 +1512,7 @@ If you have introduced private or package-protected members, you will probably have to re-write some code. Most previous uses of introducing privates can be improved by using private introduction instead. -[source,codeindent] +[source, java] ---- class C { } @@ -1458,7 +1524,8 @@ aspect AddCounter { } } -==> +// ==> + aspect AddCounter { private int Counter.count; public int Counter.getCount() { return count; } @@ -1491,7 +1558,7 @@ clause or is declared "of eachJVM()", and is not extended by another aspect, simply remove the keyword "static" from all pieces of advice, and make sure the aspect is not defined with the "abstract" modifier. -[source,codeindent] +[source, java] ---- aspect Tracing { static before(): executions(* *(..)) { @@ -1499,7 +1566,7 @@ aspect Tracing { } } -==> +// ==> aspect Tracing { before(): execution(* *(..)) { @@ -1513,7 +1580,7 @@ advice, is extended, or is "of eachObject(...)" or "of eachcflowroot(...)", you should group your static advice together and put it in a new aspect, possibly even an inner aspect. -[source,codeindent] +[source, java] ---- aspect ComplexTracing of eachobject(cflow(executions(void Main.main(..)))) { static before(): executions(* *(..)) { @@ -1526,7 +1593,7 @@ aspect ComplexTracing of eachobject(cflow(executions(void Main.main(..)))) { // some other dynamic advice, fields, etc } -==> +// ==> aspect ComplexTracing of eachobject(cflow(executions(void Main.main(..)))) { static aspect AlwaysTracing { @@ -1551,7 +1618,7 @@ majority of your code the most serious change this requires is to add an explicit `abstract` modifier to a super-aspect that was already implicitly abstract. -[source,codeindent] +[source, java] ---- aspect BaseTracing { abstract pointcut traced(); @@ -1560,11 +1627,11 @@ aspect BaseTracing { } } -==> +// ==> // make this abstract aspect explicitly abstract abstract aspect BaseTracing { - ... + // ... } ---- @@ -1576,20 +1643,22 @@ instance of a subaspect back. This pattern was used in the Spacewar example in the AspectJ distribution. We had the class hierarchy +[source, text] .... - SpaceObject (abstract) - |- Ship - |- Bullet - |- EnergyPellet +SpaceObject (abstract) + |- Ship + |- Bullet + |- EnergyPellet .... And the aspect hierarchy +[source, text] .... - SpaceObjectDA (abstract) - |- ShipDA of eachobject(instanceof(Ship)) - |- BulletDA of eachobject(instanceof(Ship)) - |- EnergyPacketDA of eachobject(instanceof(Ship)) +SpaceObjectDA (abstract) + |- ShipDA of eachobject(instanceof(Ship)) + |- BulletDA of eachobject(instanceof(Ship)) + |- EnergyPacketDA of eachobject(instanceof(Ship)) .... And we would call `SpaceObjectDA.getAspect(SpaceObject)` to access the @@ -1609,7 +1678,7 @@ defined `of eachobject(instanceof(...))`. A prime example of this was the `BoundPoint` aspect of the bean example: which needed to associate each point with a `PropertyChangeSupport` object. -[source,codeindent] +[source, java] ---- aspect BoundPoint of eachobject(instanceof(Point)) { @@ -1630,7 +1699,7 @@ these state association is to use privately introduced fields. Instead of creating an aspect instance for every `Point` object, store the `PropertyChagneSupport` object in the `Point` objects themselves. -[source,codeindent] +[source, java] ---- aspect BoundPoint { private PropertyChangeSupport Point.support = new PropertyChangeSupport(this); |