- 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>tags/V1_9_21_1
@@ -19,10 +19,10 @@ program source by using the `@` symbol. For example, the following piece | |||
of code uses the `@Deprecated` annotation to indicate that the | |||
`obsoleteMethod()` has been deprecated: | |||
[source, java] | |||
.... | |||
@Deprecated | |||
public void obsoleteMethod() { ... } | |||
.... | |||
Annotations may be _marker annotations_, _single-valued annotations_, or | |||
@@ -32,27 +32,27 @@ annotations, as in the deprecation example above. Single-value | |||
annotation types have a single member, and the annotation may be written | |||
in one of two equivalent forms: | |||
[source, java] | |||
.... | |||
@SuppressWarnings({"unchecked"}) | |||
public void someMethod() {...} | |||
.... | |||
or | |||
[source, java] | |||
.... | |||
@SuppressWarnings(value={"unchecked"}) | |||
public void someMethod() {...} | |||
.... | |||
Multi-value annotations must use the `member-name=value | |||
` syntax to specify annotation values. For example: | |||
[source, java] | |||
.... | |||
@Authenticated(role="supervisor",clearanceLevel=5) | |||
public void someMethod() {...} | |||
.... | |||
==== Retention Policies | |||
@@ -96,6 +96,7 @@ presence or absence of annotations. | |||
By default annotations are _not_ inherited. Given the following program | |||
[source, java] | |||
.... | |||
@MyAnnotation | |||
class Super { | |||
@@ -105,7 +106,6 @@ class Super { | |||
class Sub extends Super { | |||
public void foo() {} | |||
} | |||
.... | |||
Then `Sub` _does not_ have the `MyAnnotation` annotation, and | |||
@@ -133,6 +133,7 @@ permitted on pointcut declarations or on `declare` statements. | |||
The following example illustrates the use of annotations in aspects: | |||
[source, java] | |||
.... | |||
@AspectAnnotation | |||
public abstract aspect ObserverProtocol { | |||
@@ -192,6 +193,7 @@ advice statement by using the | |||
the same way as the Java 5 SuppressWarnings annotation (See JLS | |||
9.6.1.5), but has class file retention. | |||
[source, java] | |||
.... | |||
import org.aspectj.lang.annotation.SuppressAjWarnings; | |||
@@ -262,6 +264,7 @@ Some examples of annotation patterns follow: | |||
AspectJ 1.5 extends type patterns to allow an optional | |||
`AnnotationPattern` prefix. | |||
[source, text] | |||
.... | |||
TypePattern := SimpleTypePattern | | |||
'!' TypePattern | | |||
@@ -288,9 +291,9 @@ pattern, the parenthesis are required (as in `(@Foo Hello+)`). In some | |||
cases (such as a type pattern used within a `within` or `handler` | |||
pointcut expression), the parenthesis are optional: | |||
[source, text] | |||
.... | |||
OptionalParensTypePattern := AnnotationPattern? TypePattern | |||
.... | |||
The following examples illustrate the use of annotations in type | |||
@@ -330,6 +333,7 @@ patterns: | |||
A `FieldPattern` can optionally specify an annotation-matching pattern | |||
as the first element: | |||
[source, text] | |||
.... | |||
FieldPattern := | |||
AnnotationPattern? FieldModifiersPattern? | |||
@@ -371,6 +375,7 @@ annotations that match the pattern. For example: | |||
A `MethodPattern` can optionally specify an annotation-matching pattern | |||
as the first element. | |||
[source, text] | |||
.... | |||
MethodPattern := | |||
AnnotationPattern? MethodModifiersPattern? TypePattern | |||
@@ -397,6 +402,7 @@ TypePatternList := TypePattern (',' TypePattern)* | |||
A `ConstructorPattern` has the form | |||
[source, text] | |||
.... | |||
ConstructorPattern := | |||
AnnotationPattern? ConstructorModifiersPattern? | |||
@@ -470,6 +476,7 @@ Like their counterparts, these pointcut designators can be used both for | |||
join point matching, and to expose context. The format of these new | |||
designators is: | |||
[source, text] | |||
.... | |||
AtThis := '@this' '(' AnnotationOrIdentifer ')' | |||
@@ -505,6 +512,7 @@ Annotations can be exposed as context in the body of advice by using the | |||
forms of `@this(), @target()` and `@args()` that use bound variables in | |||
the place of annotation names. For example: | |||
[source, java] | |||
.... | |||
pointcut callToClassifiedObject(Classified classificationInfo) : | |||
call(* *(..)) && @target(classificationInfo); | |||
@@ -521,6 +529,7 @@ at a given position in an `@args` expression indicates that the runtime | |||
type of the argument in that position at a join point must have an | |||
annotation of the indicated type. For example: | |||
[source, java] | |||
.... | |||
/** | |||
* matches any join point with at least one argument, and where the | |||
@@ -544,6 +553,7 @@ available reflectively with the body of advice through the | |||
the arguments, or object bound to this or target at a join point you can | |||
use the following code fragments: | |||
[source, java] | |||
.... | |||
Annotation[] thisAnnotations = thisJoinPoint.getThis().getClass().getAnnotations(); | |||
Annotation[] targetAnnotations = thisJoinPoint.getTarget().getClass().getAnnotations(); | |||
@@ -555,6 +565,7 @@ point where the executing code is defined within a type (`@within`), or | |||
a method/constructor (`@withincode`) that has an annotation of the | |||
specified type. The form of these designators is: | |||
[source, text] | |||
.... | |||
AtWithin := '@within' '(' AnnotationOrIdentifier ')' | |||
AtWithinCode := '@withincode' '(' AnnotationOrIdentifier ')' | |||
@@ -574,6 +585,7 @@ The `@annotation` pointcut designator matches any join point where the | |||
_subject_ of the join point has an annotation of the given type. Like | |||
the other @pcds, it can also be used for context exposure. | |||
[source, text] | |||
.... | |||
AtAnnotation := '@annotation' '(' AnnotationOrIdentifier ')' | |||
.... | |||
@@ -589,6 +601,7 @@ extended with additional operations that provide access to the | |||
annnotations can be queried. The following fragment illustrates an | |||
example use of this interface to access annotation information. | |||
[source, java] | |||
.... | |||
Signature sig = thisJoinPointStaticPart.getSignature(); | |||
AnnotatedElement declaringTypeAnnotationInfo = sig.getDeclaringType(); | |||
@@ -621,6 +634,7 @@ considered to be an annotation on the parameter type or an annotation on | |||
the parameter itself is determined through the use of parentheses around | |||
the parameter type. Consider the following: | |||
[source, java] | |||
.... | |||
@SomeAnnotation | |||
class AnnotatedType {} | |||
@@ -634,6 +648,7 @@ class C { | |||
The method foo has a parameter of an annotated type, and can be matched | |||
by this pointcut: | |||
[source, java] | |||
.... | |||
pointcut p(): execution(* *(@SomeAnnotation *)); | |||
.... | |||
@@ -645,6 +660,7 @@ parameter of any type that has the annotation @SomeAnnotation'. | |||
To match the parameter annotation case, the method goo, this is the | |||
pointcut: | |||
[source, java] | |||
.... | |||
pointcut p(): execution(* *(@SomeAnnotation (*))); | |||
.... | |||
@@ -657,6 +673,7 @@ annotation of @SomeAnnotation'. | |||
To match when there is a parameter annotation and an annotation on the | |||
type as well: | |||
[source, java] | |||
.... | |||
pointcut p(): execution(* *(@SomeAnnotation (@SomeOtherAnnotation *))); | |||
.... | |||
@@ -671,6 +688,7 @@ According to the Java 5 specification, non-type annotations are not | |||
inherited, and annotations on types are only inherited if they have the | |||
`@Inherited` meta-annotation. Given the following program: | |||
[source, java] | |||
.... | |||
class C1 { | |||
@SomeAnnotation | |||
@@ -714,6 +732,7 @@ actually being called). | |||
The `if` pointcut designator can be used to write pointcuts that match | |||
based on the values annotation members. For example: | |||
[source, java] | |||
.... | |||
pointcut txRequiredMethod(Tx transactionAnnotation) : | |||
execution(* *(..)) && @this(transactionAnnotation) | |||
@@ -729,12 +748,14 @@ Since pointcut expressions in AspectJ 5 support join point matching | |||
based on annotations, this facility can be exploited when writing | |||
`declare warning` and `declare error` statements. For example: | |||
[source, java] | |||
.... | |||
declare warning : withincode(@PerformanceCritical * *(..)) && | |||
call(@ExpensiveOperation * *(..)) | |||
: "Expensive operation called from within performance critical section"; | |||
.... | |||
[source, java] | |||
.... | |||
declare error : call(* org.xyz.model.*.*(..)) && | |||
!@within(Trusted) | |||
@@ -745,6 +766,7 @@ declare error : call(* org.xyz.model.*.*(..)) && | |||
The general form of a `declare parents` statement is: | |||
[source, text] | |||
.... | |||
declare parents : TypePattern extends Type; | |||
declare parents : TypePattern implements TypeList; | |||
@@ -774,6 +796,7 @@ issued). | |||
The general form of a declare precedence statement is: | |||
[source, java] | |||
.... | |||
declare precedence : TypePatList; | |||
.... | |||
@@ -798,6 +821,7 @@ a future release. | |||
The general form is: | |||
[source, text] | |||
.... | |||
declare @<kind> : ElementPattern : Annotation ; | |||
.... | |||
@@ -809,6 +833,7 @@ specified by the `@Target` annotation. | |||
`ElementPattern` is defined as follows: | |||
[source, text] | |||
.... | |||
ElementPattern := TypePattern | | |||
MethodPattern | |
@@ -30,6 +30,7 @@ used to declare aspects and aspect members. | |||
Aspect declarations are supported by the | |||
`org.aspectj.lang.annotation.Aspect` annotation. The declaration: | |||
[source, java] | |||
.... | |||
@Aspect | |||
public class Foo {} | |||
@@ -37,6 +38,7 @@ public class Foo {} | |||
Is equivalent to: | |||
[source, java] | |||
.... | |||
public aspect Foo {} | |||
.... | |||
@@ -44,6 +46,7 @@ public aspect Foo {} | |||
To specify an aspect an aspect instantiation model (the default is | |||
singleton), provide the perclause as the `@Aspect` value. For example: | |||
[source, java] | |||
.... | |||
@Aspect("perthis(execution(* abc..*(..)))") | |||
public class Foo {} | |||
@@ -51,6 +54,7 @@ public class Foo {} | |||
is equivalent to... | |||
[source, java] | |||
.... | |||
public aspect Foo perthis(execution(* abc..*(..))) {} | |||
.... | |||
@@ -86,6 +90,7 @@ section. | |||
Here is a simple example of a pointcut declaration in both code and | |||
@AspectJ styles: | |||
[source, java] | |||
.... | |||
@Pointcut("call(* *.*(..))") | |||
void anyCall() {} | |||
@@ -93,6 +98,7 @@ void anyCall() {} | |||
is equivalent to... | |||
[source, java] | |||
.... | |||
pointcut anyCall() : call(* *.*(..)); | |||
.... | |||
@@ -100,6 +106,7 @@ pointcut anyCall() : call(* *.*(..)); | |||
When binding arguments, simply declare the arguments as normal in the | |||
annotated method: | |||
[source, java] | |||
.... | |||
@Pointcut("call(* *.*(int)) && args(i) && target(callee)") | |||
void anyCall(int i, Foo callee) {} | |||
@@ -107,6 +114,7 @@ void anyCall(int i, Foo callee) {} | |||
is equivalent to... | |||
[source, java] | |||
.... | |||
pointcut anyCall(int i, Foo callee) : call(* *.*(int)) && args(i) && target(callee); | |||
.... | |||
@@ -115,6 +123,7 @@ An example with modifiers (Remember that Java 5 annotations are not | |||
inherited, so the `@Pointcut` annotation must be present on the | |||
extending aspect's pointcut declaration too): | |||
[source, java] | |||
.... | |||
@Pointcut("") | |||
protected abstract void anyCall(); | |||
@@ -122,6 +131,7 @@ protected abstract void anyCall(); | |||
is equivalent to... | |||
[source, java] | |||
.... | |||
protected abstract pointcut anyCall(); | |||
.... | |||
@@ -139,6 +149,7 @@ scope. | |||
Consider the following compilation unit: | |||
[source, java] | |||
.... | |||
package org.aspectprogrammer.examples; | |||
@@ -152,6 +163,7 @@ public aspect Foo { | |||
Using the annotation style this would be written as: | |||
[source, java] | |||
.... | |||
package org.aspectprogrammer.examples; | |||
@@ -186,6 +198,7 @@ have either an empty body (`if()`, or be one of the expression forms | |||
and return a boolean. The body of the method contains the condition to | |||
be evaluated. For example: | |||
[source, java] | |||
.... | |||
@Pointcut("call(* *.*(int)) && args(i) && if()") | |||
public static boolean someCallWithIfTest(int i) { | |||
@@ -195,12 +208,14 @@ public static boolean someCallWithIfTest(int i) { | |||
is equivalent to... | |||
[source, java] | |||
.... | |||
pointcut someCallWithIfTest(int i) : call(* *.*(int)) && args(i) && if(i > 0); | |||
.... | |||
and the following is also a valid form: | |||
[source, java] | |||
.... | |||
static int COUNT = 0; | |||
@@ -260,6 +275,7 @@ method execution join point). | |||
The following example shows a simple before advice declaration in both | |||
styles: | |||
[source, java] | |||
.... | |||
@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") | |||
public void callFromFoo() { | |||
@@ -269,6 +285,7 @@ public void callFromFoo() { | |||
is equivalent to... | |||
[source, java] | |||
.... | |||
before() : call(* org.aspectprogrammer..*(..)) && this(Foo) { | |||
System.out.println("Call from Foo"); | |||
@@ -278,6 +295,7 @@ before() : call(* org.aspectprogrammer..*(..)) && this(Foo) { | |||
If the advice body needs to know which particular `Foo` instance is | |||
making the call, just add a parameter to the advice declaration. | |||
[source, java] | |||
.... | |||
before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { | |||
System.out.println("Call from Foo: " + foo); | |||
@@ -286,6 +304,7 @@ before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { | |||
can be written as: | |||
[source, java] | |||
.... | |||
@Before("call(* org.aspectprogrammer..*(..)) && this(foo)") | |||
public void callFromFoo(Foo foo) { | |||
@@ -298,6 +317,7 @@ If the advice body needs access to `thisJoinPoint` , | |||
these need to be declared as additional method parameters when using the | |||
annotation style. | |||
[source, java] | |||
.... | |||
@Before("call(* org.aspectprogrammer..*(..)) && this(foo)") | |||
public void callFromFoo(JoinPoint thisJoinPoint, Foo foo) { | |||
@@ -308,6 +328,7 @@ public void callFromFoo(JoinPoint thisJoinPoint, Foo foo) { | |||
is equivalent to... | |||
[source, java] | |||
.... | |||
before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { | |||
System.out.println("Call from Foo: " + foo + " at " | |||
@@ -317,6 +338,7 @@ before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { | |||
Advice that needs all three variables would be declared: | |||
[source, java] | |||
.... | |||
@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") | |||
public void callFromFoo(JoinPoint thisJoinPoint, | |||
@@ -340,6 +362,7 @@ To expose a return value with after returning advice simply declare the | |||
returning parameter as a parameter in the method body and bind it with | |||
the "returning" attribute: | |||
[source, java] | |||
.... | |||
@AfterReturning("criticalOperation()") | |||
public void phew() { | |||
@@ -354,6 +377,7 @@ public void itsAFoo(Foo f) { | |||
is equivalent to... | |||
[source, java] | |||
.... | |||
after() returning : criticalOperation() { | |||
System.out.println("phew"); | |||
@@ -375,6 +399,7 @@ the design goals for the annotation style is that a large class of | |||
AspectJ applications should be compilable with a standard Java 5 | |||
compiler. A straight call to `proceed` inside a method body: | |||
[source, java] | |||
.... | |||
@Around("call(* org.aspectprogrammer..*(..))") | |||
public Object doNothing() { | |||
@@ -386,6 +411,7 @@ will result in a "No such method" compilation error. For this reason | |||
AspectJ 5 defines a new sub-interface of `JoinPoint` , | |||
`ProceedingJoinPoint` . | |||
[source, java] | |||
.... | |||
public interface ProceedingJoinPoint extends JoinPoint { | |||
public Object proceed(Object[] args); | |||
@@ -394,6 +420,7 @@ public interface ProceedingJoinPoint extends JoinPoint { | |||
The around advice given above can now be written as: | |||
[source, java] | |||
.... | |||
@Around("call(* org.aspectprogrammer..*(..))") | |||
public Object doNothing(ProceedingJoinPoint thisJoinPoint) { | |||
@@ -403,6 +430,7 @@ public Object doNothing(ProceedingJoinPoint thisJoinPoint) { | |||
Here's an example that uses parameters for the proceed call: | |||
[source, java] | |||
.... | |||
@Aspect | |||
public class ProceedAspect { | |||
@@ -420,6 +448,7 @@ public class ProceedAspect { | |||
is equivalent to: | |||
[source, java] | |||
.... | |||
public aspect ProceedAspect { | |||
pointcut setAge(int i): call(* setAge(..)) && args(i); | |||
@@ -505,6 +534,7 @@ introduce a marker interface. | |||
Consider the following aspect: | |||
[source, java] | |||
.... | |||
public aspect MoodIndicator { | |||
@@ -532,6 +562,7 @@ type of the inter-type declaration). | |||
Using the annotation style this aspect can be written: | |||
[source, java] | |||
.... | |||
@Aspect | |||
public class MoodIndicator { | |||
@@ -575,6 +606,7 @@ aspect' field of a non-interface type. The interface type is the | |||
inter-type declaration contract that dictates which methods are declared | |||
on the target type. | |||
[source, java] | |||
.... | |||
// this type will be affected by the inter-type declaration as the type pattern matches | |||
package org.xyz; | |||
@@ -596,6 +628,7 @@ interface methods. | |||
Consider the following aspect: | |||
[source, java] | |||
.... | |||
public aspect SerializableMarker { | |||
declare parents : org.xyz..* implements Serializable; | |||
@@ -604,6 +637,7 @@ public aspect SerializableMarker { | |||
Using the annotation style this aspect can be written: | |||
[source, java] | |||
.... | |||
@Aspect | |||
public class SerializableMarker { | |||
@@ -620,6 +654,7 @@ implemented by the target type, an error will be issued during weaving. | |||
Consider the following aspect: | |||
[source, java] | |||
.... | |||
public aspect MoodIndicator { | |||
@@ -647,6 +682,7 @@ type of the inter-type declaration). | |||
Using the annotation style this aspect can be written: | |||
[source, java] | |||
.... | |||
@Aspect | |||
public class MoodIndicator { | |||
@@ -690,6 +726,7 @@ Exploiting this syntax requires the user to obey the rules of pure Java. | |||
So references to any targeted type as if it were affected by the Mixin | |||
must be made through a cast, like this: | |||
[source, java] | |||
.... | |||
// this type will be affected by the inter-type declaration as the type pattern matches | |||
package org.xyz; | |||
@@ -710,6 +747,7 @@ parameter. If it does, then when the factory method is called the | |||
parameter will be the object instance for which a delegate should be | |||
created: | |||
[source, java] | |||
.... | |||
@Aspect | |||
public class Foo { | |||
@@ -725,6 +763,7 @@ It is also possible to make the factory method non-static - and in this | |||
case it can then exploit the local state in the surrounding aspect | |||
instance, but this is only supported for singleton aspects: | |||
[source, java] | |||
.... | |||
@Aspect | |||
public class Foo { | |||
@@ -743,6 +782,7 @@ necessary. In this example the return type of the method extends | |||
multiple other interfaces and only a couple of them (I and J) should be | |||
mixed into any matching targets: | |||
[source, java] | |||
.... | |||
// interfaces is an array of interface classes that should be mixed in | |||
@DeclareMixin(value="org.xyz..*",interfaces={I.class,J.class}) | |||
@@ -777,6 +817,7 @@ Declare annotation is also not supported in the 1.5.0 release of AspectJ | |||
Declare precedence _is_ supported. For declare precedence, use the | |||
`@DeclarePrecedence` annotation as in the following example: | |||
[source, java] | |||
.... | |||
public aspect SystemArchitecture { | |||
declare precedence : Security*, TransactionSupport, Persistence; | |||
@@ -787,6 +828,7 @@ public aspect SystemArchitecture { | |||
can be written as: | |||
[source, java] | |||
.... | |||
@Aspect | |||
@DeclarePrecedence("Security*,org.xyz.TransactionSupport,org.xyz.Persistence") | |||
@@ -806,6 +848,7 @@ issued. | |||
Note that the String must be a literal and not the result of the | |||
invocation of a static method for example. | |||
[source, java] | |||
.... | |||
declare warning : call(* javax.sql..*(..)) && !within(org.xyz.daos..*) | |||
: "Only DAOs should be calling JDBC."; | |||
@@ -816,6 +859,7 @@ declare error : execution(* IFoo+.*(..)) && !within(org.foo..*) | |||
can be written as... | |||
[source, java] | |||
.... | |||
@DeclareWarning("call(* javax.sql..*(..)) && !within(org.xyz.daos..*)") | |||
static final String aMessage = "Only DAOs should be calling JDBC."; | |||
@@ -844,6 +888,7 @@ compilation error if another part of the program tries to call them. | |||
To provide equivalent support for AspectJ applications compiled with a | |||
standard Java 5 compiler, AspectJ 5 defines the `Aspects` utility class: | |||
[source, java] | |||
.... | |||
public class Aspects { | |||
@@ -15,6 +15,7 @@ assignments or method or constructor invocations. | |||
For example: | |||
[source, java] | |||
.... | |||
int i = 0; | |||
i = new Integer(5); // auto-unboxing | |||
@@ -28,6 +29,7 @@ Integer i2 = 5; // autoboxing | |||
Most of the pointcut designators match based on signatures, and hence | |||
are unaffected by autoboxing. For example, a call to a method | |||
[source, java] | |||
.... | |||
public void foo(Integer i); | |||
.... | |||
@@ -52,6 +54,7 @@ single argument of type `Integer` or of type `int`. | |||
Autoboxing and unboxing are also applied when binding pointcut or advice | |||
parameters, for example: | |||
[source, java] | |||
.... | |||
pointcut foo(int i) : args(i); | |||
@@ -6,6 +6,7 @@ | |||
Java 5 (and hence AspectJ 5) allows you to narrow the return type in an | |||
overriding method. For example: | |||
[source, java] | |||
.... | |||
class A { | |||
public A whoAreYou() {...} | |||
@@ -26,6 +27,7 @@ designators are extended to match against covariant methods. | |||
Given the classes `A` and `B` as defined in the previous section, and | |||
the program fragment | |||
[source, java] | |||
.... | |||
A a = new A(); | |||
B b = new B(); | |||
@@ -35,12 +37,14 @@ b.whoAreYou(); | |||
The signatures for the call join point `a.whoAreYou()` are simply: | |||
[source, java] | |||
.... | |||
A A.whoAreYou() | |||
.... | |||
The signatures for the call join point `b.whoAreYou()` are: | |||
[source, java] | |||
.... | |||
A A.whoAreYou() | |||
B B.whoAreYou() |
@@ -8,6 +8,7 @@ Java 5 (and hence AspectJ 5) provides explicit support for enumerated | |||
types. In the simplest case, you can declare an enumerated type as | |||
follows: | |||
[source, java] | |||
.... | |||
public enum ProgrammingLanguages { | |||
COBOL, C, JAVA, ASPECTJ |
@@ -15,6 +15,7 @@ the type name. By convention formal type parameters are named using a | |||
single letter, though this is not required. A simple generic list type | |||
(that can contain elements of any type `E`) could be declared: | |||
[source, java] | |||
.... | |||
interface List<E> { | |||
Iterator<E> iterator(); | |||
@@ -63,6 +64,7 @@ parameterized type by specifying a concrete type specfication for each | |||
type parameter in the generic type. The following example declares a | |||
list of strings and a list of numbers: | |||
[source, java] | |||
.... | |||
List<String> strings; | |||
List<Number> numbers; | |||
@@ -78,6 +80,7 @@ written in the Java 5 language would not be expected to use raw types. | |||
Parameterized types are instantiated by specifying type parameter values | |||
in the constructor call expression as in the following examples: | |||
[source, java] | |||
.... | |||
List<String> strings = new MyListImpl<String>(); | |||
List<Number> numbers = new MyListImpl<Number>(); | |||
@@ -135,6 +138,7 @@ The supertype of a generic type `C` is the type given in the extends | |||
clause of `C`, or `Object` if no extends clause is present. Given the | |||
type declaration | |||
[source, java] | |||
.... | |||
public interface List<E> extends Collection<E> {... } | |||
.... | |||
@@ -164,6 +168,7 @@ type `List<? extends Number>`. | |||
A static method may be declared with one or more type parameters as in | |||
the following declaration: | |||
[source, java] | |||
.... | |||
static <T> T first(List<T> ts) { ... } | |||
.... | |||
@@ -174,6 +179,7 @@ not need to be declared as a type parameter of the enclosing type. | |||
Non-static methods may also be declared with one or more type parameters | |||
in a similar fashion: | |||
[source, java] | |||
.... | |||
<T extends Number> T max(T t1, T t2) { ... } | |||
.... | |||
@@ -215,6 +221,7 @@ generic type. | |||
Generic methods and constructors, and members defined in generic types, | |||
may use type variables as part of their signature. For example: | |||
[source, java] | |||
.... | |||
public class Utils { | |||
@@ -334,6 +341,7 @@ types (methods) and field types (fields). This is achieved by specifying | |||
a parameterized type pattern at the appropriate point in the signature | |||
pattern. For example, given the class `Foo`: | |||
[source, java] | |||
.... | |||
public class Foo { | |||
@@ -376,6 +384,7 @@ expression `call(* addStrings(List))` and by the expression | |||
Remember that any type variable reference in a generic member is | |||
_always_ matched by its erasure. Thus given the following example: | |||
[source, java] | |||
.... | |||
class G<T> { | |||
List<T> foo(List<String> ls) { return null; } | |||
@@ -396,6 +405,7 @@ different type to `List<String>`, even though a variable of type | |||
`List<String>` can be assigned to a variable of type `List<?>`. Given | |||
the methods: | |||
[source, java] | |||
.... | |||
class C { | |||
public void foo(List<? extends Number> listOfSomeNumberType) {} | |||
@@ -423,6 +433,7 @@ Under certain circumstances a Java 5 compiler is required to create | |||
_bridge methods_ that support the compilation of programs using raw | |||
types. Consider the types | |||
[source, java] | |||
.... | |||
class Generic<T> { | |||
public T foo(T someObject) { | |||
@@ -445,6 +456,7 @@ in `Generic`. This is an example of a case where a Java 5 compiler will | |||
create a _bridge method_ in `SubGeneric`. Although you never see it, the | |||
bridge method will look something like this: | |||
[source, java] | |||
.... | |||
public Object foo(Object arg) { | |||
Number n = (Number) arg; // "bridge" to the signature defined in this type | |||
@@ -464,6 +476,7 @@ It _is_ possible to _call_ a bridge method as the following short code | |||
snippet demonstrates. Such a call _does_ result in a call join point for | |||
the call to the method. | |||
[source, java] | |||
.... | |||
SubGeneric rawType = new SubGeneric(); | |||
rawType.foo("hi"); // call to bridge method (will result in a runtime failure in this case) | |||
@@ -483,6 +496,7 @@ types with the `this()` and `target()` pointcuts. Parameterized types | |||
may however be used in conjunction with `args()`. Consider the following | |||
class | |||
[source, java] | |||
.... | |||
public class C { | |||
public void foo(List<String> listOfStrings) {} | |||
@@ -513,6 +527,7 @@ args(List<Double>):: | |||
instance of List at join point method-execution(void C.goo(List<? | |||
extends Number>)) [Xlint:uncheckedArgument]"; | |||
[source, java] | |||
.... | |||
public aspect A { | |||
before(List<Double> listOfDoubles) : execution(* C.*(..)) && args(listOfDoubles) { | |||
@@ -533,6 +548,7 @@ pointcut associated with the advice will be suppressed. To suppress just | |||
an `uncheckedArgument` warning, use the annotation | |||
`@SuppressWarnings("uncheckedArgument")` as in the following examples: | |||
[source, java] | |||
.... | |||
import org.aspectj.lang.annotation.SuppressAjWarnings | |||
public aspect A { | |||
@@ -560,6 +576,7 @@ following example the advice will match the execution of `bar` but not | |||
of `goo` since the signature of `goo` is not matched by the execution | |||
pointcut expression. | |||
[source, java] | |||
.... | |||
public aspect A { | |||
before(List<Double> listOfDoubles) : execution(* C.*(List<Double>)) && args(listOfDoubles) { | |||
@@ -580,6 +597,7 @@ an `uncheckedArgument` warning. | |||
Consider the following program: | |||
[source, java] | |||
.... | |||
public class C { | |||
public static void main(String[] args) { | |||
@@ -622,6 +640,7 @@ to a method declared to take a `List<? extends Number>`, | |||
matching to only those join points at which the argument is guaranteed | |||
to be an instance of `List<? extends Number>`. | |||
[source, java] | |||
.... | |||
aspect A { | |||
before(List<? extends Number> aListOfSomeNumberType) | |||
@@ -641,6 +660,7 @@ described for args. For example, the following aspect matches the | |||
execution of any method returning a `List`, and makes the returned list | |||
available to the body of the advice. | |||
[source, java] | |||
.... | |||
public aspect A { | |||
pointcut executionOfAnyMethodReturningAList() : execution(List *(..)); | |||
@@ -661,6 +681,7 @@ we only perform safe operations on the list. | |||
Given the class | |||
[source, java] | |||
.... | |||
public class C { | |||
public List<String> foo(List<String> listOfStrings) {...} | |||
@@ -676,6 +697,7 @@ bind the return value. It will also run after the execution of `goo` and | |||
bind the return value, but gives an `uncheckedArgument` warning during | |||
compilation. It does _not_ run after the execution of `foo`. | |||
[source, java] | |||
.... | |||
public aspect Returning { | |||
after() returning(List<Double> listOfDoubles) : execution(* C.*(..)) { | |||
@@ -701,6 +723,7 @@ reference, and not a raw type reference. | |||
Consider the generic type `Generic` with a pointcut `foo`: | |||
[source, java] | |||
.... | |||
public class Generic<T> { | |||
/** | |||
@@ -713,6 +736,7 @@ public class Generic<T> { | |||
Such a pointcut must be refered to using a parameterized reference as | |||
shown below. | |||
[source, java] | |||
.... | |||
public aspect A { | |||
// runs before the execution of any implementation of a method defined for MyClass | |||
@@ -813,6 +837,7 @@ permitted in this parameterization. | |||
Given the aspect declaration: | |||
[source, java] | |||
.... | |||
public abstract aspect ParentChildRelationship<P,C> { | |||
... | |||
@@ -843,6 +868,7 @@ within inter-type declarations_. For example, we can declare a | |||
`ParentChildRelationship` aspect to manage the bi-directional | |||
relationship between parent and child nodes as follows: | |||
[source, java] | |||
.... | |||
/** | |||
* a generic aspect, we've used descriptive role names for the type variables | |||
@@ -939,6 +965,7 @@ parent and child. In a compiler implementation managing an abstract | |||
syntax tree (AST) in which AST nodes may contain other AST nodes we | |||
could declare the concrete aspect: | |||
[source, java] | |||
.... | |||
public aspect ASTNodeContainment extends ParentChildRelationship<ASTNode,ASTNode> { | |||
before(ASTNode parent, ASTNode child) : addingChild(parent, child) { | |||
@@ -965,6 +992,7 @@ void setParent(ASTNode parent) | |||
In a system managing orders, we could declare the concrete aspect: | |||
[source, java] | |||
.... | |||
public aspect OrderItemsInOrders extends ParentChildRelationship<Order, OrderItem> { | |||
} | |||
@@ -991,6 +1019,7 @@ void setParent(Order parent) | |||
A second example of an abstract aspect, this time for handling | |||
exceptions in a uniform manner, is shown below: | |||
[source, java] | |||
.... | |||
abstract aspect ExceptionHandling<T extends Throwable> { | |||
@@ -1024,6 +1053,7 @@ of the aspect to be designed to work together in a type-safe manner. The | |||
following concrete sub-aspect shows how the abstract aspect might be | |||
extended to handle `IOExceptions`. | |||
[source, java] | |||
.... | |||
public aspect IOExceptionHandling extends ExceptionHandling<IOException>{ | |||
@@ -1,6 +1,7 @@ | |||
[[grammar]] | |||
== A Grammar for the AspectJ 5 Language | |||
[source, text] | |||
.... | |||
=== type patterns === | |||
@@ -25,6 +25,7 @@ A kinded pointcut is written using patterns, some of which match based | |||
on _signature_, and some of which match based on _modifiers_. For | |||
example, in the `call` pointcut designator: | |||
[source, text] | |||
.... | |||
call(ModifierPattern TypePattern TypePattern.IdPattern(TypePatternList) ThrowsPattern) | |||
.... | |||
@@ -96,6 +97,7 @@ For a call join point where a call is made to a method | |||
`m(parameter_types)` on a target type `T` (where `T` is the static type | |||
of the target): | |||
[source, java] | |||
.... | |||
T t = new T(); | |||
t.m("hello"); <= call join point occurs when this line is executed | |||
@@ -108,6 +110,7 @@ declare a definition of `m(parameter_types)`, then `R(T)` is the return | |||
type in the definition of `m` that `T` inherits. Given the call above, | |||
and the definition of `T.m`: | |||
[source, java] | |||
.... | |||
interface Q { | |||
R m(String s); | |||
@@ -135,6 +138,7 @@ signature of the call join point, where `R(A)` is the return type of ` | |||
Continuing the example from above,we can deduce that | |||
[source, java] | |||
.... | |||
R' S.m(String) | |||
R P.m(String) | |||
@@ -151,6 +155,7 @@ different declaring type. | |||
Join point signatures for execution join points are defined in a similar | |||
manner to signatures for call join points. Given the hierarchy: | |||
[source, java] | |||
.... | |||
interface Q { | |||
R m(String s); | |||
@@ -174,6 +179,7 @@ class U extends T { | |||
Then the execution join point signatures arising as a result of the call | |||
to `u.m("hello")` are: | |||
[source, java] | |||
.... | |||
R' U.m(String) | |||
R' S.m(String) | |||
@@ -198,6 +204,7 @@ If `T` does not directly declare a member `f`, then for each super type | |||
does declare the member `f`, `F S.f` is a signature of the join point. | |||
For example, given the hierarchy: | |||
[source, java] | |||
.... | |||
class P { | |||
F f; | |||
@@ -213,6 +220,7 @@ class T extends S { } | |||
Then the join point signatures for a field get join point of the field | |||
`f` on an object with declared type `T` are: | |||
[source, java] | |||
.... | |||
F S.f | |||
F T.f | |||
@@ -263,6 +271,7 @@ chain. | |||
For example, given the following types | |||
[source, java] | |||
.... | |||
public class X { | |||
@Foo | |||
@@ -293,6 +302,7 @@ point | |||
Given the hierarchy | |||
[source, java] | |||
.... | |||
interface Q { | |||
R m(String s); | |||
@@ -313,6 +323,7 @@ class T extends S {} | |||
and the program fragment: | |||
[source, java] | |||
.... | |||
P p = new P(); | |||
S s = new S(); |
@@ -8,6 +8,7 @@ AspectJ 5 is more liberal than AspectJ 1.2.1 in accepting pointcut | |||
expressions that bind context variables in more than one location. For | |||
example, AspectJ 1.2.1 does not allow: | |||
[source, java] | |||
.... | |||
pointcut foo(Foo foo) : (execution(* *(..)) && this(foo) ) || | |||
(set(* *) && target(foo)); | |||
@@ -28,6 +29,7 @@ exceptions. If the exception type specified in a declare soft statement | |||
is `RuntimeException` or a subtype of `RuntimeException` then a new | |||
XLint warning will be issued: | |||
[source, java] | |||
.... | |||
declare soft : SomeRuntimeException : execution(* *(..)); | |||
@@ -43,6 +45,7 @@ _checked_ exception thrown at a matched join point, where the exception | |||
is an instance of the softened exception, will be softened to an | |||
`org.aspectj.lang.SoftException`. | |||
[source, java] | |||
.... | |||
public aspect SoftenExample { | |||
declare soft : Exception : execution(* Foo.*(..)); |
@@ -5,6 +5,7 @@ AspectJ 5 defines a new per-clause type for aspect instantiation: | |||
`pertypewithin`. Unlike the other per-clauses, `pertypewithin` takes a | |||
type pattern: | |||
[source, text] | |||
.... | |||
PerTypeWithin := 'pertypewithin' '(' OptionalParensTypePattern ')' | |||
.... | |||
@@ -16,6 +17,7 @@ the associated type pattern. | |||
Pertypewithin aspects have `aspectOf` and `hasAspect` methods with the | |||
following signatures: | |||
[source, java] | |||
.... | |||
/** | |||
* return true if this aspect has an instance associated with | |||
@@ -37,6 +39,7 @@ In addition, `pertypewithin` aspects have a `getWithinTypeName` method | |||
that can be called to return the package qualified name of the type for | |||
which the aspect instance has been created. | |||
[source, java] | |||
.... | |||
/** | |||
* return the package qualified name (eg. com.foo.MyClass) of the type | |||
@@ -51,6 +54,7 @@ upon an implicit pointcut condition. In this case, that any join point | |||
be `within` the type that the executing aspect is an `aspectOf`. For | |||
example, given the aspect definition | |||
[source, java] | |||
.... | |||
import java.util.*; | |||
@@ -7,6 +7,7 @@ Java 5 (and hence AspectJ 5) allows you to specify methods that take a | |||
variable number of arguments of a specified type. This is achieved using | |||
an ellipsis (...) in the method signature as shown: | |||
[source, java] | |||
.... | |||
public void foo(int i, String... strings) { | |||
} | |||
@@ -21,6 +22,7 @@ A _varargs_ method may be called with zero or more arguments in the | |||
variable argument position. For example, given the definition of `foo` | |||
above, the following calls are all legal: | |||
[source, java] | |||
.... | |||
foo(5); | |||
foo(5,"One String"); | |||
@@ -31,6 +33,7 @@ foo(3,"One String","Two Strings","Three Strings"); | |||
A _varargs_ parameter is treated as an array within the defining member. | |||
So in the body of `foo` we could write for example: | |||
[source, java] | |||
.... | |||
public void foo(int i, String... strings) { | |||
String[] someStrings = strings; | |||
@@ -41,6 +44,7 @@ public void foo(int i, String... strings) { | |||
One consequence of this treatment of a varargs parameter as an array is | |||
that you can also call a varargs method with an array: | |||
[source, java] | |||
.... | |||
foo(7,new String[] {"One String","Two Strings"}); | |||
.... | |||
@@ -63,6 +67,7 @@ annotations (xref:annotations.adoc#signaturePatterns[Signature Patterns]), that | |||
`ConstructorPattern` are extended to allow a `varargs` pattern in the | |||
last argument position of a method or constructor signature. | |||
[source, text] | |||
.... | |||
FormalsPattern := '..' (',' FormalsPatternAfterDotDot)? | | |||
OptionalParensTypePattern (',' FormalsPattern)* | | |||
@@ -93,6 +98,7 @@ initialization(org.xyz.*.new((Foo || Goo)...)):: | |||
A variable argument parameter and an array parameter are treated as | |||
distinct signature elements, so given the method definitions: | |||
[source, java] | |||
.... | |||
void foo(String...); | |||
void bar(String[]); | |||
@@ -110,6 +116,7 @@ array type, as discussed in the introduction to this section. We follow | |||
the same convention when binding a varargs parameter via the `args` | |||
pointcut designator. Given a method | |||
[source, java] | |||
.... | |||
public void foo(int i, String... strings) { | |||
} | |||
@@ -123,6 +130,7 @@ syntax within an args pointcut designator - so you _cannot_ write | |||
Binding of a varargs parameter in an advice statement is | |||
straightforward: | |||
[source, java] | |||
.... | |||
before(int i, String[] ss) : call(* foo(int,String...)) && args(i,ss) { | |||
// varargs String... argument is accessible in advice body through ss |
@@ -27,6 +27,7 @@ xref:ltw.adoc#ltw[Load-Time Weaving]. | |||
Use ajc to build a library, then weave at load time | |||
[source, text] | |||
.... | |||
REM compile library | |||
${ASPECTJ_HOME}\bin\ajc.bat -outjar lib\aspects.jar @aspects.lst |
@@ -17,9 +17,9 @@ invoke the script in `{aspectj}/bin` (if AspectJ is installed correctly) | |||
or by using the `aspectjtools.jar` directly, and specifying no arguments | |||
or some number of build configuration files (suffix `.lst`): | |||
[source, text] | |||
.... | |||
java -jar aspectj1.1/lib/aspectjtools.jar aspectj1.1/doc/examples/spacewar/debug.lst | |||
.... | |||
[[ajbrowser-building]] |
@@ -146,6 +146,7 @@ destination directory on the inpath and rebuild.) | |||
Emit warnings for any instances of the comma-delimited list of | |||
questionable code (eg '-warn:unusedLocals,deprecation'): | |||
+ | |||
[source, text] | |||
.... | |||
constructorName method with constructor name | |||
packageDefaultMethod attempt to override package-default method | |||
@@ -168,6 +169,7 @@ none suppress all compiler warnings | |||
-g<:[lines,vars,source]>:: | |||
debug attributes level, that may take three forms: | |||
+ | |||
[source, text] | |||
.... | |||
-g all debug info ('-g:lines,vars,source') | |||
-g:none no debug info | |||
@@ -261,6 +263,7 @@ previous releases of AspectJ, see xref:compatibility.adoc#versionCompatibility[V | |||
Compile two files: | |||
[source, text] | |||
.... | |||
ajc HelloWorld.java Trace.java | |||
.... | |||
@@ -271,6 +274,7 @@ relative to the argfile, and may include other argfiles by @-reference. | |||
The following file `sources.lst` contains absolute and relative files | |||
and @-references: | |||
[source, text] | |||
.... | |||
Gui.java | |||
/home/user/src/Library.java | |||
@@ -283,6 +287,7 @@ view/body/ArrayView.java | |||
Compile the files using either the -argfile or @ form: | |||
[source, text] | |||
.... | |||
ajc -argfile sources.lst | |||
ajc @sources.lst | |||
@@ -317,6 +322,7 @@ sources with the aspect library. | |||
The tracing example is in the AspectJ distribution | |||
(\{aspectj}/doc/examples/tracing). This uses the following files: | |||
[source, text] | |||
.... | |||
aspectj1.1/ | |||
bin/ | |||
@@ -346,6 +352,7 @@ environment as needed. | |||
Setup the path, classpath, and current directory: | |||
[source, text] | |||
.... | |||
cd examples | |||
export ajrt=../lib/aspectjrt.jar | |||
@@ -355,18 +362,21 @@ export PATH="../bin:$PATH" | |||
Build a read-only tracing library: | |||
[source, text] | |||
.... | |||
ajc -argfile tracing/tracelib.lst -outjar tracelib.jar | |||
.... | |||
Build the application with tracing in one step: | |||
[source, text] | |||
.... | |||
ajc -aspectpath tracelib.jar -argfile tracing/notrace.lst -outjar tracedapp.jar | |||
.... | |||
Run the application with tracing: | |||
[source, text] | |||
.... | |||
java -classpath "$ajrt;tracedapp.jar;tracelib.jar" tracing.ExampleMain | |||
.... | |||
@@ -376,6 +386,7 @@ Build the application with tracing from binaries in two steps: | |||
* (a) Build the application classes (using javac for | |||
demonstration's sake): | |||
+ | |||
[source, text] | |||
.... | |||
mkdir classes | |||
javac -d classes tracing/*.java | |||
@@ -383,18 +394,21 @@ jar cfM app.jar -C classes . | |||
.... | |||
* (b) Build the application with tracing: | |||
+ | |||
[source, text] | |||
.... | |||
ajc -inpath app.jar -aspectpath tracelib.jar -outjar tracedapp.jar | |||
.... | |||
Run the application with tracing (same as above): | |||
[source, text] | |||
.... | |||
java -classpath "$ajrt;tracedapp.jar;tracelib.jar" tracing.ExampleMain | |||
.... | |||
Run the application without tracing: | |||
[source, text] | |||
.... | |||
java -classpath "app.jar" tracing.ExampleMain | |||
.... | |||
@@ -418,6 +432,7 @@ to collect the messages, use `MessageHandler` as your `IMessageHolder`. | |||
For example, compile and run the following with `aspectjtools.jar` on | |||
the classpath: | |||
[source, java] | |||
.... | |||
import org.aspectj.bridge.*; | |||
import org.aspectj.tools.ajc.Main; | |||
@@ -454,6 +469,7 @@ the -XnoInline option.) | |||
Probably the only time you may see this format is when you view stack | |||
traces, where you may encounter traces of the format | |||
[source, text] | |||
.... | |||
java.lang.NullPointerException | |||
at Main.new$constructor_call37(Main.java;SynchAspect.java[1k]:1030) | |||
@@ -461,12 +477,14 @@ java.lang.NullPointerException | |||
where instead of the usual | |||
[source, text] | |||
.... | |||
File:LineNumber | |||
.... | |||
format, you see | |||
[source, text] | |||
.... | |||
File0;File1[Number1];File2[Number2] ... :LineNumber | |||
.... |
@@ -133,7 +133,7 @@ Pass a non-standard option to the VM | |||
=== Capabilities | |||
The AspectJ debugger implements all of `jdb`'s commands. In addition, | |||
The AspectJ debugger implements all of ``jdb``'s commands. In addition, | |||
the command `workingdir` allow you to set the AspectJ working directory, | |||
and the breakpoint command, `stop on`, has been extended to allow the | |||
setting of breakpoint on a source file line. | |||
@@ -158,25 +158,25 @@ For this example, we need to set the source path by: ` | |||
To view the file to debug, type `list | |||
spacewar/Ship.java` which generates the following output: | |||
[source, java] | |||
.... | |||
209 void fire() { | |||
210 // firing a shot takes energy | |||
211 if (!expendEnergy(BULLET_ENERGY)) | |||
212 return; | |||
213 | |||
214 //create a bullet object so it doesn't hit the ship that's firing it | |||
215 double xV = getXVel() + BULLET_SPEED * (Math.cos(orientation)); | |||
216 double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); | |||
217 | |||
218 // create the actual bullet | |||
219 new Bullet( | |||
220 getGame(), | |||
221 (getXPos() + ((getSize()/2 + 2) * (Math.cos(orientation))) + xV), | |||
222 (getYPos() + ((getSize()/2 + 2) * (Math.sin(orientation))) + yV), | |||
223 xV, | |||
224 yV); | |||
225 } | |||
/*209*/ void fire() { | |||
/*210*/ // firing a shot takes energy | |||
/*211*/ if (!expendEnergy(BULLET_ENERGY)) | |||
/*212*/ return; | |||
/*213*/ | |||
/*214*/ //create a bullet object so it doesn't hit the ship that's firing it | |||
/*215*/ double xV = getXVel() + BULLET_SPEED * (Math.cos(orientation)); | |||
/*216*/ double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); | |||
/*217*/ | |||
/*218*/ // create the actual bullet | |||
/*219*/ new Bullet( | |||
/*220*/ getGame(), | |||
/*221*/ (getXPos() + ((getSize()/2 + 2) * (Math.cos(orientation))) + xV), | |||
/*222*/ (getYPos() + ((getSize()/2 + 2) * (Math.sin(orientation))) + yV), | |||
/*223*/ xV, | |||
/*224*/ yV); | |||
/*225*/ } | |||
.... | |||
This is different from `jdb` because it allows one to view files before | |||
@@ -222,88 +222,88 @@ The following message appears notifying the user that the breakpoint has | |||
been noted but will not be set until the class has been loaded by the | |||
VM: | |||
[source, text] | |||
.... | |||
Deferring breakpoint spacewar.Ship.fire() | |||
It will be set after the class is loaded. | |||
.... | |||
To start Spacewar we type `run spacewar.Game`. | |||
When the breakpoint is set, the following message appears: | |||
[source, text] | |||
.... | |||
Set deferred breakpoint spacewar.Ship.fire() | |||
.... | |||
We are notified that we've hit the breakpoint: | |||
[source, text] | |||
.... | |||
Breakpoint hit: thread="Thread-2", spacewar.Ship.fire(), line=174, bci=0 209 void fire() { | |||
.... | |||
The prompt changes to present the thread that has broken, and we can | |||
view the current stack with the `where` command, as follows: | |||
[source, text] | |||
.... | |||
Thread-2[1] where | |||
[1] fire (spacewar\Ship.java:209) | |||
[2] run (spacewar\Robot.java:100) | |||
[3] run [class java.lang.Thread] | |||
.... | |||
Next, to stop on line 216 we type `stop on spacewar/Ship.java:216` | |||
The following message tells us the breakpoint was set: | |||
[source, text] | |||
.... | |||
Set breakpoint Ship.java:216 | |||
.... | |||
To continue execution, we type `cont` and the breakpoint at line 216 is | |||
hit | |||
[source, text] | |||
.... | |||
Breakpoint hit: thread="Thread-2", spacewar.Ship.fire(), line=216, bci=28 | |||
216 double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); | |||
.... | |||
To view the visible local variables, we type `locals` and ajdb responds | |||
with: | |||
[source, text] | |||
.... | |||
Local variables | |||
xV = 12.242462584304468 | |||
.... | |||
To change the value of the local variable i to 15, we type | |||
`set xV = 16.1` | |||
[source, text] | |||
.... | |||
Changed 'xV' from '12.242462584304468' to '16.1' | |||
.... | |||
To see our changes we can print the value of `i` by the following: | |||
[source, text] | |||
.... | |||
print xV | |||
Value for printing 'xV' = 12.242462584304468 | |||
.... | |||
We can now type exit or quit to leave the debugger, and we receive the | |||
following message: | |||
[source, text] | |||
.... | |||
The application has exited. | |||
.... | |||
=== The AspectJ debugger API | |||
@@ -314,13 +314,10 @@ the method `org.aspectj.tools.debugger.Main.main(String[] | |||
args)` where `args` are the standard `ajc` command line arguments. | |||
This means that an alternative way to run the compiler is | |||
java org.aspectj.tools.debugger.Main | |||
option | |||
class | |||
arguments | |||
[source, text] | |||
.... | |||
java org.aspectj.tools.debugger.Main options class arguments | |||
.... | |||
You must additionally include `tools.jar` from your Java developer's kit | |||
in your classpath. |
@@ -123,6 +123,7 @@ enable AspectJ mode on a per-project basis. | |||
your `load-path` and are ``required''. This is an example for the 1.0 | |||
release: | |||
+ | |||
[source, text] | |||
.... | |||
;; I keep my emacs packages in C:/Emacs | |||
(setq load-path | |||
@@ -140,7 +141,6 @@ load-path)) | |||
(require 'jde) | |||
(require 'ajdee) ; can also appear in prj.el | |||
.... | |||
. _[Optional]_ add `-emacssym` switch to the `ajc` and `ajc.bat` files | |||
in your AspectJ tools installations (in the `/bin` directory). If you | |||
@@ -152,6 +152,7 @@ following in your `.emacs` file or in a JDE project file `prj.el` in | |||
your project's hierarchy (see the `JDE Project File Name` option for the | |||
latter). Here is a simple example: | |||
+ | |||
[source, text] | |||
.... | |||
;; A default version for simple projects, maybe good for | |||
;;; .emacs file. | |||
@@ -161,11 +162,11 @@ latter). Here is a simple example: | |||
;; ajc requires all files to be named for a compile | |||
'(aspectj-compile-file-specification "*.java")) | |||
.... | |||
+ | |||
Here is an example for spacewar, in `examples/spacewar`. | |||
+ | |||
[source, text] | |||
.... | |||
;;; These options are for the spacewar, in examples/spacewar. | |||
(custom-set-variables | |||
@@ -180,7 +181,6 @@ Here is an example for spacewar, in `examples/spacewar`. | |||
'(jde-compile-option-directory "..") | |||
'(jde-run-working-directory "..")) | |||
'(jde-run-application-class "spacewar.Game") | |||
.... | |||
. _[XEmacs only]_ If you're installing JDE yourself, be sure to closely | |||
follow the JDE installation directions for XEmacs, otherwise you may get | |||
@@ -207,6 +207,7 @@ for problems not specific to AJDEE's features. | |||
* _Symptom_: Get standard speedbar menus in JDE; no annotations display. | |||
Message: | |||
+ | |||
[source, text] | |||
.... | |||
AspectJ Mode Warning: Can't find declarations file for... | |||
.... | |||
@@ -235,6 +236,7 @@ AspectJ project's directory (see sample.prj in the distribution). | |||
* _Symptom_: Reported bug fixes and new features to AJDEE are not seen, | |||
or ajdee.el cannot be found or loaded, with message: | |||
+ | |||
[source, text] | |||
.... | |||
Error in init file: File error: "Cannot open load file", "ajdee" | |||
.... |
@@ -34,6 +34,7 @@ argfile (`@filename`) conventions as with `ajc`. For example, the | |||
following documents all the source files listed in `argfile.lst`, | |||
sending the output to the `docDir` output directory. | |||
[source, text] | |||
.... | |||
ajdoc -d docDir @argfile.lst | |||
.... |
@@ -38,6 +38,7 @@ in `${ANT_HOME}/lib` where it will be added to the system class path by | |||
the ant script. You may specify the task script names directly, or use | |||
the "resource" attribute to specify the default names: | |||
[source, xml] | |||
.... | |||
<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"/> | |||
.... | |||
@@ -50,6 +51,7 @@ In Ant 1.6, third-party tasks are declared in their own namespace using | |||
spacewar example, if you put the script in the examples directory and | |||
`aspectjtools.jar` in the `${ANT_HOME}/lib` directory. | |||
[source, xml] | |||
.... | |||
<project name="aspectj-ant1.6" default="spacewar" | |||
xmlns:aspectj="antlib:org.aspectj" basedir="."> | |||
@@ -340,6 +342,7 @@ elements; these are `sourceroots`, `argfiles`, `injars`, `inpath`, | |||
`classpath`, `bootclasspath`, `forkclasspath`, and `aspectpath`. In all | |||
cases, these may be specified as nested elements, something like this: | |||
[source, xml] | |||
.... | |||
<iajc {attributes..} /> | |||
<{name}> | |||
@@ -354,6 +357,7 @@ cases, these may be specified as nested elements, something like this: | |||
As with other Path-like structures, they may be defined elsewhere and | |||
specified using the refid attribute: | |||
[source, xml] | |||
.... | |||
<path id="aspect.path"> | |||
<pathelement path="${home}/lib/persist.jar"/> | |||
@@ -369,6 +373,7 @@ specified using the refid attribute: | |||
The task also supports an attribute `{name}ref` for each such parameter. | |||
E.g., for `aspectpath`: | |||
[source, xml] | |||
.... | |||
<iajc {attributes..} aspectpathref="aspect.path"/> | |||
.... | |||
@@ -379,6 +384,7 @@ E.g., for `aspectpath`: | |||
A minimal build script defines the task and runs it, specifying the | |||
sources: | |||
[source, xml] | |||
.... | |||
<project name="simple-example" default="compile" > | |||
<taskdef | |||
@@ -410,6 +416,7 @@ When this target is built, the compiler will build once and then wait | |||
for input from the user. Messages are printed as usual. When the user | |||
has quit, then this runs the application. | |||
[source, xml] | |||
.... | |||
<target name="build-test" > | |||
<iajc outjar="${home.dir}/output/application.jar" | |||
@@ -453,6 +460,7 @@ case where no files have been updated, there is no reason to recompile | |||
sources. One way to implement that is with an explicit dependency check | |||
using the uptodate task: | |||
[source, xml] | |||
.... | |||
<target name="check.aspects.jar"> | |||
<uptodate property="build.unnecessary" | |||
@@ -512,6 +520,7 @@ example, the call below passes all out-of-date source files in the | |||
`src/org/aspectj` subdirectories to the `ajc` command along with the | |||
destination directory: | |||
[source, text] | |||
.... | |||
-- command: | |||
@@ -525,6 +534,7 @@ destination directory: | |||
To pass ajc-specific arguments, use a compilerarg entry. | |||
[source, text] | |||
.... | |||
-- command | |||
@@ -598,6 +608,7 @@ This tells the compiler adapter to delete all .class files in the | |||
destination directory and re-execute the javac task so javac can | |||
recalculate the list of source files. e.g., | |||
+ | |||
[source, text] | |||
.... | |||
Ant -Dbuild.compiler=org.aspectj.tools.ant.taskdefs.Ajc11CompilerAdapter | |||
-Dbuild.compiler.clean=anything ... | |||
@@ -746,7 +757,7 @@ This task forms an implicit FileSet and supports all attributes of | |||
`<exclude>`, and `<patternset>` elements. These can be used to specify | |||
source files. | |||
`ajc`'s `srcdir`, `classpath`, `bootclasspath`, `extdirs`, and `jvmarg` | |||
``ajc``'s `srcdir`, `classpath`, `bootclasspath`, `extdirs`, and `jvmarg` | |||
attributes are path-like structures and can also be set via nested | |||
`<src>`, `<classpath>`, `<bootclasspath>`, `<extdirs>`, and `<jvmargs>` | |||
elements, respectively. | |||
@@ -758,6 +769,7 @@ Following is a declaration for the ajc task and a sample invocation that | |||
uses the ajc compiler to compile the files listed in `default.lst` into | |||
the dest dir: | |||
[source, xml] | |||
.... | |||
<project name="example" default="compile" > | |||
<taskdef name="ajc" | |||
@@ -782,6 +794,7 @@ the dest dir: | |||
This build script snippet | |||
[source, xml] | |||
.... | |||
<ajc srcdir="${src}" | |||
destdir="${build}" | |||
@@ -796,6 +809,7 @@ are included. | |||
This next example | |||
[source, xml] | |||
.... | |||
<ajc srcdir="${src}" | |||
destdir="${build}" |
@@ -103,11 +103,11 @@ initialization file `sample.emacs` in the distribution. | |||
. The files in this package need to be in the load-path and | |||
``required''. For example, for the 1.0 release: | |||
+ | |||
[source, text] | |||
.... | |||
;; I keep my emacs packages in C:/Emacs | |||
(setq load-path (cons "C:/Emacs/aspectj-emacsMode-1.0" load-path)) | |||
(require 'aspectj-mode) | |||
.... | |||
. _[Optional]_ add `-emacssym` switch to the `ajc` and `ajc.bat` files | |||
in your AspectJ tools installations (in the `/bin` directory). If you | |||
@@ -130,6 +130,7 @@ given in the file `sample.emacs` in the distribution. | |||
* _Symptom_: No annotations show. Message: | |||
+ | |||
[source, text] | |||
.... | |||
AspectJ Mode Warning: Can't find declarations file for... | |||
.... | |||
@@ -160,6 +161,7 @@ menu. | |||
* _Symptom_: Reported bug fixes and new features to aspectj-mode are not | |||
seen, or aspectj-mode.el cannot be found or loaded, with message: | |||
+ | |||
[source, text] | |||
.... | |||
Error in init file: File error: "Cannot open load file", "aspectj-mode" | |||
.... |
@@ -125,6 +125,7 @@ Aspects defined in this way must extend an abstract aspect visible to | |||
the weaver. The abstract aspect may define abstract pointcuts (but not | |||
abstract methods). The following example shows a simple aop.xml file: | |||
[source, xml] | |||
.... | |||
<aspectj> | |||
@@ -260,6 +261,7 @@ pointcuts at deployment time, and also gives control over precedence | |||
through the `precedence` attribute of the `concrete-aspect` XML element. | |||
Consider the following: | |||
[source, java] | |||
.... | |||
package mypack; | |||
@@ -272,13 +274,14 @@ public abstract class AbstractAspect { | |||
@Before("scope() && execution(* *..doSome(..))") | |||
public void before(JoinPoint jp) { | |||
.... | |||
// ... | |||
} | |||
} | |||
.... | |||
This aspect is equivalent to the following in code style: | |||
[source, java] | |||
.... | |||
package mypack; | |||
@@ -288,7 +291,7 @@ public abstract aspect AbstractAspect { | |||
abstract pointcut scope(); | |||
before() : scope() && execution(* *..doSome(..)) { | |||
.... | |||
// ... | |||
} | |||
} | |||
.... | |||
@@ -318,6 +321,7 @@ If more complex aspect inheritance is required use regular aspect | |||
inheritance instead of XML. The following XML definition shows a valid | |||
concrete sub-aspect for the abstract aspects above: | |||
[source, xml] | |||
.... | |||
<aspectj> | |||
<aspects> | |||
@@ -339,6 +343,7 @@ aspect instance(s) (depending on the perclause of the aspect it extends) | |||
you have to use the helper API `org.aspectj.lang.Aspects.aspectOf(..)` | |||
as in: | |||
[source, java] | |||
.... | |||
// exception handling omitted | |||
Class myConcreteAspectClass = Class.forName("mypack.__My__AbstractAspect"); | |||
@@ -359,6 +364,7 @@ abstract aspect. It is therefore possible to use the `concrete-aspect` | |||
element without the `extends` attribute and without any `pointcut` | |||
nested elements, just a `precedence` attribute. Consider the following: | |||
[source, xml] | |||
.... | |||
<aspectj> | |||
<aspects> | |||
@@ -459,6 +465,7 @@ weaving configuration files. | |||
When using Java 5 the JVMTI agent can be used by starting the JVM with | |||
the following option (adapt according to the path to aspectjweaver.jar): | |||
[source, text] | |||
.... | |||
-javaagent:pathto/aspectjweaver.jar | |||
.... |
@@ -4,6 +4,7 @@ _Last updated: 2004-03-15 by acolyer_ | |||
== How Compilation Progresses in the JDT | |||
[source, text] | |||
.... | |||
Compiler.compile(ICompilationUnit[] sourceUnits) { | |||
@@ -35,6 +36,7 @@ passed to the compiler, and the code generation phase is optional | |||
== How (batch) Compilation Progresses in AspectJ 1.1.x | |||
[source, text] | |||
.... | |||
AjBuildManager.doBuild() { | |||
@@ -90,6 +92,7 @@ that do different things). | |||
This simple model ignores aspectpath, inpath, injars, outjar, | |||
sourceDirs for now. | |||
[source, text] | |||
.... | |||
Compiler.compile(ICompilationUnit[] sourceUnits) { | |||
@@ -65,6 +65,7 @@ code generation | |||
Let's trace the following example program through the compiler. | |||
[source, java] | |||
.... | |||
package example.parse.tree; | |||
@@ -99,6 +100,7 @@ image:top-tree.gif[image] | |||
Let's look more closely at the pointcut declaration: | |||
[source, java] | |||
.... | |||
pointcut entries(Main o): execution(void doit()) && this(o); | |||
.... | |||
@@ -114,6 +116,7 @@ information might be needed to implement a declare soft. | |||
Next we look at the processing for an advice declaration: | |||
[source, java] | |||
.... | |||
before(Main o): entries(o) { | |||
o.counter++; | |||
@@ -262,6 +265,7 @@ failures, resolve them with the AspectJ developers before moving on. | |||
{empty}a. Create a new file in tests/design/pcds/Throw.java | |||
[source, java] | |||
.... | |||
import org.aspectj.testing.Tester; | |||
@@ -290,6 +294,7 @@ aspect A { | |||
{empty}b. Create a temporary test harness file to run just this test in | |||
myTests.xml | |||
[source, xml] | |||
.... | |||
<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"> | |||
<suite> | |||
@@ -303,6 +308,7 @@ myTests.xml | |||
{empty}c. Run this test using the harness. You should see: | |||
[source, text] | |||
.... | |||
about to execute: execution(void Throws.willThrow()) | |||
about to execute: call(java.lang.RuntimeException(String)) | |||
@@ -314,6 +320,7 @@ PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 2 seconds | |||
Modify runtime/org.aspectj.lang/JoinPoint.java to add a name for the | |||
Throw shadow kind. | |||
[source, java] | |||
.... | |||
static String THROW = "throw"; | |||
.... | |||
@@ -328,6 +335,7 @@ This is because the throw bytecode in Java operates on a single argument | |||
that is a Throwable which must be the top element on the stack. This | |||
argument is removed from the stack by the bytecode. | |||
[source, java] | |||
.... | |||
public static final Kind Throw = new Kind(JoinPoint.THROW, 12, true); | |||
.... | |||
@@ -335,6 +343,7 @@ public static final Kind Throw = new Kind(JoinPoint.THROW, 12, true); | |||
We also modify the neverHasTarget method to include the Throw kind | |||
because in Java there is no target for the throwing of an exception. | |||
[source, java] | |||
.... | |||
public boolean neverHasTarget() { | |||
return this == ConstructorCall | |||
@@ -348,6 +357,7 @@ public boolean neverHasTarget() { | |||
In the read method on Shadow.Kind, add another case to read in our new | |||
Shadow.Kind. | |||
[source, java] | |||
.... | |||
case 12: return Throw; | |||
.... | |||
@@ -357,6 +367,7 @@ case 12: return Throw; | |||
Modify weaver/org.aspectj.weaver.bcel/BcelClassWeaver.java to recognize | |||
this new joinpoint kind. In the method | |||
[source, java] | |||
.... | |||
private void match( | |||
LazyMethodGen mg, | |||
@@ -368,6 +379,7 @@ private void match( | |||
Add a test for this instruction, i.e. | |||
[source, java] | |||
.... | |||
} else if (i == InstructionConstants.ATHROW) { | |||
match(BcelShadow.makeThrow(world, mg, ih, enclosingShadow), | |||
@@ -378,6 +390,7 @@ Add a test for this instruction, i.e. | |||
Then, modify BcelShadow.java to create this new kind of join point | |||
shadow: | |||
[source, java] | |||
.... | |||
public static BcelShadow makeThrow( | |||
BcelWorld world, | |||
@@ -408,6 +421,7 @@ public static BcelShadow makeThrow( | |||
Finally modify weaver/org.aspectj.weaver/Member.java to generate the | |||
needed signature | |||
[source, java] | |||
.... | |||
public static Member makeThrowSignature(TypeX inType, TypeX throwType) { | |||
return new Member( | |||
@@ -421,6 +435,7 @@ public static Member makeThrowSignature(TypeX inType, TypeX throwType) { | |||
Run the proto test again and you should see: | |||
[source, text] | |||
.... | |||
about to execute: execution(void Throws.willThrow()) | |||
about to execute: call(java.lang.RuntimeException(String)) | |||
@@ -439,6 +454,7 @@ part of the clean-up. For now, let's go on with the interesting parts. | |||
Add a second piece of before advice to the test aspect A: | |||
[source, java] | |||
.... | |||
before(): throw(Throwable) { | |||
System.out.println("about to throw: " + thisJoinPoint); | |||
@@ -448,6 +464,7 @@ before(): throw(Throwable) { | |||
When we run the test again we'll get a long error message from the | |||
harness. The interesting part of the message is the following: | |||
[source, text] | |||
.... | |||
[ 0] [error 0]: error can't find referenced pointcut at C:\aspectj\eclipse\tests\design\pcds\Throws.java:23:0 | |||
.... | |||
@@ -470,6 +487,7 @@ Modify the parseSinglePointcut method in | |||
weaver/org.aspectj.weaver.patterns/PatternParser.java to add one more | |||
else if clause for the throw pcd: | |||
[source, java] | |||
.... | |||
} else if (kind.equals("throw")) { | |||
parseIdentifier(); eat("("); | |||
@@ -485,6 +503,7 @@ else if clause for the throw pcd: | |||
Modify the matches method in | |||
weaver/org.aspectj.weaver.patterns/SignaturePattern.java to add: | |||
[source, java] | |||
.... | |||
if (kind == Member.HANDLER) { | |||
return parameterTypes.matches(world.resolve(sig.getParameterTypes()), | |||
@@ -494,6 +513,7 @@ if (kind == Member.HANDLER) { | |||
Run the proto test again and you should see: | |||
[source, text] | |||
.... | |||
about to execute: execution(void Throws.willThrow()) | |||
about to execute: call(java.lang.RuntimeException(String)) | |||
@@ -513,6 +533,7 @@ case. Modify our test aspect A to be the following. In addition to | |||
removing the overly generic withincode pcd, this change also prints the | |||
actual object that is about to be thrown: | |||
[source, java] | |||
.... | |||
aspect A { | |||
before(Throwable t): throw(*) && args(t) { | |||
@@ -523,6 +544,7 @@ aspect A { | |||
When we run the test again we should see the output below: | |||
[source, text] | |||
.... | |||
about to throw: 'java.lang.RuntimeException: expected exception' at throw(catch(Throwable)) | |||
PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 1 seconds | |||
@@ -546,6 +568,7 @@ exception thrown to be 'Throwable'. Can we set this to be more accurate? | |||
Looking at the source code, it seems easy to identify the static type of | |||
the exception that is thrown: | |||
[source, java] | |||
.... | |||
throw new RuntimeException("expected exception"); | |||
.... | |||
@@ -585,6 +608,7 @@ thrown, we need to fix the parser for the throw pcd to remove this | |||
information. We'll fix the PatternParser code that we added in step 1.6 | |||
to read as follows: | |||
[source, java] | |||
.... | |||
} else if (kind.equals("throw")) { | |||
parseIdentifier(); eat("("); | |||
@@ -602,6 +626,7 @@ before. To make this work we have a set of things to do. First, let's | |||
create this new kind in org.aspectj.weaver.Member. Find where the | |||
HANDLER kind is defined there, and add a corresponding throw kind: | |||
[source, java] | |||
.... | |||
public static final Kind THROW = new Kind("THROW", 8); | |||
.... | |||
@@ -610,6 +635,7 @@ We also need to fix the serialization kind in | |||
Member.Kind.read(DataInputStream) just above this constant list to add a | |||
case for this new kind: | |||
[source, java] | |||
.... | |||
case 8: return THROW; | |||
.... | |||
@@ -617,6 +643,7 @@ case 8: return THROW; | |||
Still in this file, we also need to fix Member.makeThrowSignature to use | |||
this new kind: | |||
[source, java] | |||
.... | |||
public static Member makeThrowSignature(TypeX inType, TypeX throwType) { | |||
return new ResolvedMember( | |||
@@ -631,6 +658,7 @@ public static Member makeThrowSignature(TypeX inType, TypeX throwType) { | |||
If you run the test now you'll get an error from the parser reminding us | |||
that the throw pcd now doesn't accept a type pattern: | |||
[source, text] | |||
.... | |||
------------ FAIL: simple throw join point() | |||
... | |||
@@ -642,6 +670,7 @@ FAIL Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 failed) 1 seconds | |||
This is an easy fix to the test case as we modify our pcd for the new | |||
syntax in the aspect A in our Throws.java test code: | |||
[source, java] | |||
.... | |||
before(Throwable t): throw() && args(t) { | |||
.... | |||
@@ -649,6 +678,7 @@ before(Throwable t): throw() && args(t) { | |||
Now when we run the test case it looks like everything's fixed and we're | |||
passing: | |||
[source, text] | |||
.... | |||
PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 2 seconds | |||
.... | |||
@@ -664,6 +694,7 @@ that by adding code that notes when the advice runs and then checks for | |||
this event. This code uses the Tester.event and Tester.checkEvent | |||
methods: | |||
[source, java] | |||
.... | |||
import org.aspectj.testing.Tester; | |||
@@ -694,6 +725,7 @@ aspect A { | |||
Now when we run our test case it will fail. This failure is good because | |||
we're not matching the throw join point anymore. | |||
[source, text] | |||
.... | |||
------------ FAIL: simple throw join point() | |||
... | |||
@@ -711,6 +743,7 @@ use combinations with other pcds to narrow their matches. So, find the | |||
line for kind == Member.ADVICE and add the same line below it for | |||
Member.THROW. | |||
[source, java] | |||
.... | |||
if (kind == Member.ADVICE) return true; | |||
if (kind == Member.THROW) return true; | |||
@@ -727,6 +760,7 @@ kind of printing back on the see what's happening. If you uncomment to | |||
System.out.println in the test aspect A and rerun the test, you won't be | |||
very happy with the results: | |||
[source, text] | |||
.... | |||
------------ FAIL: simple throw join point() | |||
... | |||
@@ -752,6 +786,7 @@ signature, these classes are extremely simple. Nevertheless, we have to | |||
build them. Notice that when we add new source files to the system we | |||
need to include the standard eclipse EPL license header. | |||
[source, java] | |||
.... | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 Contributors. | |||
@@ -771,6 +806,7 @@ import org.aspectj.lang.Signature; | |||
public interface ThrowSignature extends Signature { } | |||
.... | |||
[source, java] | |||
.... | |||
/* ******************************************************************* | |||
* Copyright (c) 2006 Contributors. | |||
@@ -807,6 +843,7 @@ To finish up our work in the runtime module, we need to extend | |||
org.aspectj.runtime.reflect.Factory to add a factory method for this new | |||
signature kind: | |||
[source, java] | |||
.... | |||
public ThrowSignature makeThrowSig(String stringRep) { | |||
ThrowSignatureImpl ret = new ThrowSignatureImpl(stringRep); | |||
@@ -822,6 +859,7 @@ first place. First let's add a method to create a string for the throw | |||
signature. This is a very simple method copied from the other | |||
create*SignatureString methods. | |||
[source, java] | |||
.... | |||
private String getThrowSignatureString(World world) { | |||
StringBuffer buf = new StringBuffer(); | |||
@@ -836,6 +874,7 @@ private String getThrowSignatureString(World world) { | |||
Now we need to modify three methods to add cases for the new | |||
Member.THROW kind. First, Member.getSignatureMakerName add: | |||
[source, java] | |||
.... | |||
} else if (kind == THROW) { | |||
return "makeThrowSig"; | |||
@@ -843,6 +882,7 @@ Member.THROW kind. First, Member.getSignatureMakerName add: | |||
Next, to Member.getSignatureType add: | |||
[source, java] | |||
.... | |||
} else if (kind == THROW) { | |||
return "org.aspectj.lang.reflect.ThrowSignature"; | |||
@@ -850,6 +890,7 @@ Next, to Member.getSignatureType add: | |||
Finally, to Member.getSignatureString add: | |||
[source, java] | |||
.... | |||
} else if (kind == THROW) { | |||
return getThrowSignatureString(world); | |||
@@ -859,6 +900,7 @@ With all of these changes in place we should have working code for | |||
thisJoinPoint reflection using our new join point and signature kinds. | |||
Rerun the test to confirm: | |||
[source, text] | |||
.... | |||
about to throw: 'java.lang.RuntimeException: expected exception' at throw(throw) | |||
PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 1 seconds | |||
@@ -869,6 +911,7 @@ PASS Suite.Spec(c:\aspectj\eclipse\tests) 1 tests (1 passed) 1 seconds | |||
Modify the before advice to include at least minimal checks of the new | |||
reflective information: | |||
[source, java] | |||
.... | |||
before(Throwable t): throw() && args(t) { | |||
Tester.event("before throw"); | |||
@@ -908,6 +951,7 @@ tests. | |||
You should expect to see at least one other test case fail when you run | |||
ajcTests.xml. Here's the failure message: | |||
[source, text] | |||
.... | |||
------------ FAIL: validate (enclosing) join point and source locations() | |||
... | |||
@@ -948,6 +992,7 @@ that the only occurence of throw is just before the handler for | |||
catch(Error) and right after the call to new Error. We should add our | |||
new expected event between these two: | |||
[source, text] | |||
.... | |||
, "before AllTargetJoinPoints call(java.lang.Error(String))" | |||
, "before AllTargetJoinPoints throw(throw)" // added for new throw join point | |||
@@ -964,6 +1009,7 @@ to make sure that the new join point kind is compatible with all 5 kinds | |||
of advice. Let's extend our current simple Throws test to check for | |||
before and the three kinds of after advice: | |||
[source, java] | |||
.... | |||
import org.aspectj.testing.Tester; | |||
@@ -1019,6 +1065,7 @@ point kind work for before and all three kinds of after advice. | |||
Let's create a new test case to see how this new join point interacts | |||
with around advice. | |||
[source, java] | |||
.... | |||
import org.aspectj.testing.Tester; | |||
@@ -1050,6 +1097,7 @@ aspect A { | |||
When we run this test case we get a very unpleasant result: | |||
[source, text] | |||
.... | |||
------------ FAIL: simple throw join point with around() | |||
... | |||
@@ -1080,6 +1128,7 @@ implemented in the org.aspectj.weaver.Shadow.match(Shadow, World) | |||
method. We can add our new rule at the beginning of the if(kind == | |||
AdviceKind.Around) block: | |||
[source, java] | |||
.... | |||
} else if (kind == AdviceKind.Around) { | |||
if (shadow.getKind() == Shadow.Throw) { | |||
@@ -1093,6 +1142,7 @@ AdviceKind.Around) block: | |||
Now if we rerun our test we'll see errors telling us that around is | |||
prohibited on throw join points: | |||
[source, text] | |||
.... | |||
------------ FAIL: simple throw join point with around() | |||
... | |||
@@ -1106,6 +1156,7 @@ To finish this test case up we need to modify the specification to be | |||
looking for these errors as the correct behavior. This will produce the | |||
following specification: | |||
[source, xml] | |||
.... | |||
<ajc-test dir="design/pcds" | |||
title="simple throw join point with around"> |
@@ -50,6 +50,7 @@ http://asm.objectweb.org/download/. | |||
The ASM license is available at http://asm.objectweb.org/license.html. | |||
The license is also reproduced here: | |||
[source, text] | |||
.... | |||
Copyright (c) 2000-2005 INRIA, France Telecom | |||
All rights reserved. |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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() | |||
.... |
@@ -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) * *(..)) { |
@@ -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); | |||
} | |||
.... | |||
''''' |
@@ -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 | |||
.... |
@@ -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() { |
@@ -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(); |
@@ -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. | |||
''''' |
@@ -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) |
@@ -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 |
@@ -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> |
@@ -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 | |||
} | |||
.... |
@@ -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 | |||
.... |
@@ -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< === | |||
.... |
@@ -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 |
@@ -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(* *(..))) | |||
.... |
@@ -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 | |||
.... |
@@ -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 |
@@ -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) { |
@@ -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 |
@@ -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 |
@@ -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()) |
@@ -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 |
@@ -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); |
@@ -140,9 +140,9 @@ must be able to reach classes in the small (< 100K) runtime library | |||
*A:* From AspectJ's http://eclipse.org/aspectj[web page] , download the | |||
AspectJ distribution. The `jar` file is installed by executing | |||
[source, text] | |||
.... | |||
java -jar jar file name | |||
.... | |||
Do *not* try to extract the `jar` file contents and then attempt to | |||
@@ -503,6 +503,7 @@ AKA agile methods)? | |||
*A:* From a question on the user list: | |||
[source, text] | |||
.... | |||
> Anyone know the connections between AOP and Extreme Programming? | |||
> I am really confused. It seems AOP is a programming paradigm, which | |||
@@ -510,7 +511,6 @@ AKA agile methods)? | |||
> this is a lightweight software development process. One of the common | |||
> motivations of AOP and XP is designed to adopt to the requirement | |||
> changes, so that it can save the cost of software development. | |||
.... | |||
This is Raymond Lee's answer: | |||
@@ -649,6 +649,7 @@ in a modular way, something that would otherwise be spread throughout | |||
the code. Consider the following code, adapted from the AspectJ | |||
tutorial: | |||
[source, java] | |||
.... | |||
aspect PublicErrorLogging { | |||
Log log = new Log(); | |||
@@ -660,7 +661,6 @@ aspect PublicErrorLogging { | |||
log.write(o, e); | |||
} | |||
} | |||
.... | |||
The effect of this code is to ensure that whenever any public method of | |||
@@ -838,6 +838,7 @@ below shows how the different profiles build on top of the two | |||
configurations CDC (Connected Device Configuration) and CLDC (Connected | |||
Limited Device Configuration): | |||
[source, text] | |||
.... | |||
-------------- | |||
| Personal | | |||
@@ -848,7 +849,6 @@ Limited Device Configuration): | |||
------------------------------------------ | |||
| Java | | |||
------------------------------------------ | |||
.... | |||
Which configuration you have dictates the restrictions when running | |||
@@ -1007,18 +1007,18 @@ Environment Guide] link:devguide/ajc-ref.html[Reference for ajc]. | |||
line-delimited text file and direct ajc to that file using `-argfile` or | |||
`@`: | |||
[source, text] | |||
.... | |||
ajc @sources.lst | |||
ajc -argfile sources.lst | |||
.... | |||
Another way in AspectJ 1.1 is to use the `-sourceroots` options, which | |||
reads all source files in a given set of directories: | |||
[source, text] | |||
.... | |||
ajc -sourceroots "src;testsrc" | |||
.... | |||
For more information, see the link:devguide/index.html[Development | |||
@@ -1063,23 +1063,23 @@ Here's an example of using `ajc` in this sort of cross-compilation mode | |||
(assuming a Windows platform with all the default installation | |||
directories): | |||
[source, text] | |||
.... | |||
ajc -target 1.1 -bootclasspath c:\jdk1.1.7\lib\classes.zip \ | |||
-classpath c:\aspectj1.0\lib\aspectjrt.jar -extdirs "" \ | |||
-argfile jdk11system.lst | |||
.... | |||
This same technique can be used if you want to run `ajc` on a JDK 1.3 | |||
JVM (highly recommended) but need to generate code for JDK 1.2. That | |||
would look something like: | |||
[source, text] | |||
.... | |||
ajc -bootclasspath c:\jdk1.2\jre\lib\rt.jar \ | |||
-classpath c:\aspectj1.0\lib\aspectjrt.jar \ | |||
-extdirs c:\jdk1.2\jre\lib\ext | |||
-argfile jdk12system.lst | |||
.... | |||
*Q:* Does the `ajc` compiler support the `assert` keyword in Java 1.4? | |||
@@ -1226,10 +1226,10 @@ which will be affected by any advice specifying the same pointcut. For | |||
example, the following will print a warning whereever some code in class | |||
Bar gets a field value from Foo: | |||
[source, java] | |||
.... | |||
declare warning: get(* Foo.*) && within(Bar) | |||
: "reading Foo state from Bar"; | |||
.... | |||
When you are running your program, you can trace advice as it executes. | |||
@@ -1282,6 +1282,7 @@ use implement a hybrid build process by listing the production source | |||
files into a javac-compliant argfile, and the development source files | |||
in another ajc argfiles: | |||
[source, text] | |||
.... | |||
-- file "production.lst": | |||
One.java | |||
@@ -1295,21 +1296,20 @@ Trace.java | |||
-- file "development.lst": | |||
@production.lst | |||
@tracing.lst | |||
.... | |||
Then your development build can use `ajc`: | |||
[source, text] | |||
.... | |||
ajc @development.lst | |||
.... | |||
And your development build can use `ajc` or `javac` or `jikes`: | |||
[source, text] | |||
.... | |||
jikes @production.lst | |||
.... | |||
*Q:* We compile module jars and then assemble them. Can we continue this | |||
@@ -1331,6 +1331,7 @@ are visible to other clients, which themselves are otherwise unaffected | |||
by the aspects. In this case, the common library can be built using ajc, | |||
and used on the classpath for the module builds: | |||
[source, text] | |||
.... | |||
ajc -outjar common.jar -sourceroots "aspectj-src:src" ... | |||
cd ../otherProject | |||
@@ -1342,6 +1343,7 @@ should affect two or more modules that are in a dependency relationship | |||
to one another. It should work to reuse the aspects in binary form for | |||
each compile, in dependency order: | |||
[source, text] | |||
.... | |||
ajc -outjar common-aspects.jar | |||
-sourceroots "aspectj-src" ... | |||
@@ -1380,6 +1382,7 @@ libraries). | |||
In Eclipse's AJDT, you can create a top-level project with symbolic | |||
links out to the sources: | |||
[source, text] | |||
.... | |||
app-assembly/ | |||
{link common/aspects} | |||
@@ -1425,6 +1428,7 @@ Here's some code Jim Hugunin wrote to trace join points and posted to | |||
the users list. To reuse the aspect, define a subaspect and implement | |||
the pointcuts, for example: | |||
[source, java] | |||
.... | |||
aspect JoinPointSampleAspect extends aj.TraceJoinPoints { | |||
protected pointcut entry() : | |||
@@ -1442,11 +1446,11 @@ aspect JoinPointSampleAspect extends aj.TraceJoinPoints { | |||
class JoinPointSample { | |||
public static void main(String[] args) {} | |||
} | |||
.... | |||
Here's the aspect: | |||
[source, java] | |||
.... | |||
/* TraceJoinPoints.java */ | |||
@@ -1639,6 +1643,7 @@ call? How about the most-recent prior entrypoint? | |||
most-recent recursive call or (b) the current and original recursive | |||
call: | |||
[source, java] | |||
.... | |||
aspect LogFactorial { | |||
pointcut f(int i) : call(int factorial(int)) && args(i); | |||
@@ -1654,7 +1659,6 @@ aspect LogFactorial { | |||
System.err.println(i + "@" + j); | |||
} | |||
} | |||
.... | |||
*Q:* What is the difference between constructor call, constructor | |||
@@ -1672,6 +1676,7 @@ constructor call obtained using `TraceJointPoints.java` from | |||
#q:seeingjoinpoints[Q:I don't understand what join points exist. How can | |||
I see them?]. | |||
[source, java] | |||
.... | |||
public class Init { | |||
public static void main (String[] args) { | |||
@@ -1689,6 +1694,7 @@ class Test extends Super implements I { | |||
For a program compiled with AspectJ 1.0, the result is this: | |||
[source, xml] | |||
.... | |||
<constructor-call sig="Test()" > | |||
<staticinitialization sig="Super._init_" /> | |||
@@ -1723,9 +1729,9 @@ of thumb: | |||
* If you want the join point on the "outside" of object creation, use | |||
after returning from call to the constructor: | |||
+ | |||
[source, java] | |||
.... | |||
after() returning (Foo newlyCreatedObject): call(Foo.new(..)) { ... } | |||
.... | |||
+ | |||
You might be tempted to use "this" or "target" to expose the new object, | |||
@@ -1734,9 +1740,9 @@ object itself might not be created yet... it only exists "on the way | |||
out", when you return the object. | |||
* If you want the join point inside a particular constructor, use: | |||
+ | |||
[source, java] | |||
.... | |||
after(Foo newlyCreatedObject) returning: this(newlyCreatedObject) && execution(Foo.new(..)) { ... } | |||
.... | |||
+ | |||
Remember, though, that if you use "before" advice here, the body of the | |||
@@ -1747,9 +1753,9 @@ object that call each other with `this(...)` and you want exactly one | |||
join point for each initialization of `Foo`, regardless of the path of | |||
constructors it takes, then use: | |||
+ | |||
[source, java] | |||
.... | |||
after(Foo f) returning: this(f) && initialization(Foo.new(..)) { ... } | |||
.... | |||
*Q:* I want advice to run at two join points, but it doesn't run at all. | |||
@@ -1759,9 +1765,9 @@ What gives? | |||
mistake. Most likely you want to do something like "run the advice for | |||
all public and private calls," and the code looks something like this: | |||
[source, java] | |||
.... | |||
within(com.xerox.printing..*) && call(public * *(..)) && call(private * *(..)) | |||
.... | |||
But a pointcut is evaluated at *each* join point. The expression above | |||
@@ -1770,9 +1776,9 @@ has both public and private access. In a pointcut, `pc1() && pc2()` | |||
means both must be true at a given join point for advice to run at that | |||
join point. The correct pointcut would use `||` as follows: | |||
[source, java] | |||
.... | |||
within(com.xerox.printing..*) && (call(public * *(..)) || call(private * *(..))) | |||
.... | |||
Then the advice will run at the join point. | |||
@@ -1796,6 +1802,7 @@ limited to a certain set of classes. Do I have to retype it each time? | |||
*A:* No. You can declare that all the types implement an interface you | |||
define, and then use the interface type in your program. For example: | |||
[source, java] | |||
.... | |||
/** | |||
* Example of using an interface to represent a type pattern. | |||
@@ -1821,7 +1828,6 @@ abstract aspect MarkerExample { | |||
aspect MyMarker extends MarkerExample { | |||
declare parents: com.mycompany.whatever..* implements Marked; | |||
} | |||
.... | |||
*Q:* Where do I find example programs and how-to's? | |||
@@ -1886,6 +1892,7 @@ Specification] . | |||
here is the HTML code for an HTML editor applet that contains some | |||
debugging aspects: | |||
[source, xml] | |||
.... | |||
<APPLET | |||
CODE='com.company.swing.applets.EditorApplet' | |||
@@ -1914,6 +1921,7 @@ types to Object, so that highly polymorphic advice may be written. This | |||
works if an advice parameter or the return type for around is typed to | |||
Object. So: | |||
[source, java] | |||
.... | |||
class Test { | |||
static int i; | |||
@@ -1928,15 +1936,14 @@ aspect TraceSet { | |||
System.err.println(val.class); | |||
} | |||
} | |||
.... | |||
will print out | |||
[source, text] | |||
.... | |||
37 | |||
java.lang.Integer | |||
.... | |||
For more information, see the Programming Guide | |||
@@ -1951,10 +1958,10 @@ flag as an argument. | |||
To programmatically detect the version of the AspectJ runtime while | |||
running under Java 1.4 or later, get the version from the package: | |||
[source, java] | |||
.... | |||
Package lang = org.aspectj.lang.JoinPoint.class.getPackage(); | |||
String version = lang.getImplementationVersion(); | |||
.... | |||
When running under Java 1.3 or earlier, read the manifest directly. For | |||
@@ -1973,13 +1980,13 @@ in `org.aspectj.bridge.Version`. | |||
*A:* The only modifier advice can take is `strictfp`. However, you can | |||
enclose the body of the advice in a synchronized clause: | |||
[source, java] | |||
.... | |||
before() : pc() { | |||
synchronized (this) { | |||
// advice code here | |||
} | |||
} | |||
.... | |||
It should not be necessary to synchronize a percflow aspect, but you | |||
@@ -1999,6 +2006,7 @@ VM exhausts itself in the recursion. | |||
Of course, infinite recursion is possible in Java: | |||
[source, java] | |||
.... | |||
public class Main { | |||
public static void main(String[] args) { | |||
@@ -2009,7 +2017,6 @@ public class Main { | |||
} | |||
} | |||
} | |||
.... | |||
If you compile and run this program, and it will fail silently, trying | |||
@@ -2018,11 +2025,11 @@ StackOverflowError. | |||
Here's a similar AspectJ program where the recursion is not so obvious: | |||
[source, java] | |||
.... | |||
aspect A { | |||
after(): call(* *(..)) { System.out.println("after " + thisJoinPoint); } | |||
} | |||
.... | |||
This re-invokes itself because it advises any call. It invokes itself | |||
@@ -2042,19 +2049,20 @@ finally clause, understanding that it may run after some failure. | |||
{empty}(2) Avoid writing advice that advises itself. One simple way to | |||
do so is to exclude the code within the current aspect: | |||
[source, java] | |||
.... | |||
aspect A { | |||
after() returning: !within(A) && call(* *(..)) { | |||
System.out.println("after " + thisJoinPoint); | |||
} | |||
} | |||
.... | |||
A better way is often to re-write the pointcut. If the advice is | |||
advising itself accidentally, that's a sign that the pointcut is not | |||
saying what you mean. | |||
[source, java] | |||
.... | |||
aspect A { | |||
pointcut withinTargetClasses() : within(A+) || within(B+); | |||
@@ -2062,12 +2070,12 @@ aspect A { | |||
System.out.println("after " + thisJoinPoint); | |||
} | |||
} | |||
.... | |||
*Q:* I've declared a field on every class in my package; how do I use it | |||
in advice? | |||
[source, java] | |||
.... | |||
aspect A { | |||
boolean com.xerox..*.dirtyFlag; | |||
@@ -2076,7 +2084,6 @@ aspect A { | |||
target.dirtyFlag = true; // compile fails here | |||
} | |||
} | |||
.... | |||
*A:* You need a type to refer to any member, field or method. It's | |||
@@ -2084,6 +2091,7 @@ generally better to introduce onto an interface and declare classes to | |||
implement the interface, which permits you to use the interface type in | |||
advice formals. | |||
[source, java] | |||
.... | |||
aspect A { | |||
interface TrackingSets {} | |||
@@ -2095,7 +2103,6 @@ aspect A { | |||
target.dirtyFlag = true; | |||
} | |||
} | |||
.... | |||
*Q:* The AspectJ compiler aborts with an OutOfMemoryError when compiling | |||
@@ -2182,6 +2189,7 @@ How can I fix this?]. For your IDE, do something similar or follow the | |||
provider's instructions. For example, to increase memory in JBuilder, | |||
edit the `jbuilderX/bin/jbuilder.config` file to have an entry like: | |||
[source, text] | |||
.... | |||
vmparam -Xmx384m | |||
.... | |||
@@ -2430,6 +2438,7 @@ not control the code for the method execution), test the context for | |||
`invoke(..)`. Here's a pointcut that tests only if the method name is | |||
correct: | |||
[source, java] | |||
.... | |||
aspect A { | |||
pointcut runReflectiveCall(Method run) : target(run) && | |||
@@ -2438,7 +2447,6 @@ aspect A { | |||
System.out.println("before reflective call " + thisJoinPoint); | |||
} | |||
} | |||
.... | |||
*Q:* What are the bugs now most affecting users? | |||
@@ -2502,11 +2510,11 @@ CGLIB generate code from the weaving process by appropriate use of the | |||
exclude element in the aop.xml. A typical clause in the aop.xml might | |||
look as follows: | |||
[source, xml] | |||
.... | |||
<weaver> | |||
<exclude within="*CGLIB*" /> | |||
</weaver> | |||
.... | |||
[[aj11]] | |||
@@ -2653,6 +2661,7 @@ only XML. This means aspect developers can write abstract aspects, and | |||
deployers need only configure `aop.xml` and run using the AspectJ weaver | |||
in Java 5. For example, to run Java 5 VM with load-time weaving, | |||
[source, text] | |||
.... | |||
java -javaagent:aspectjweaver.jar -classpath "aspects.jar:${CLASSPATH}" .. | |||
.... | |||
@@ -2661,6 +2670,7 @@ To declare a concrete aspect, add a a concrete-aspect XML entity to | |||
`META-INF/aop.xml`. This example extends a tracing aspect to apply to | |||
every type in the application: | |||
[source, xml] | |||
.... | |||
<concrete-aspect | |||
name="com.company.tracing.ConcreteTracing" | |||
@@ -2987,10 +2997,10 @@ AJDT development environment and running the correctness tests. Then: | |||
* Create a file `aspectjlib.properties` within the `org.aspectj.ajde` | |||
project and add the following two lines | |||
+ | |||
[source, text] | |||
.... | |||
aspectj.lib.dir=C:/eclipse/aspectj-workspace/aj-build/dist/tools/lib | |||
aspectj.doc.dir=C:/eclipse/aspectj-workspace/aj-build/dist/ide/eclipse/org.aspectj.ajde.doc/doc | |||
.... | |||
+ | |||
making sure to change the path to correspond to your set up. | |||
@@ -3043,6 +3053,7 @@ is a sample file with some example definitions, preceded by comments | |||
showing the directory layout of the files referred to in the test | |||
definitions. | |||
[source, xml] | |||
.... | |||
<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"> | |||
<suite> | |||
@@ -3137,10 +3148,10 @@ tree as described in #q:buildingsource[Q:How do I get and compile the | |||
source code for AspectJ?] and then build the `build-testing-drivers` | |||
target: | |||
[source, text] | |||
.... | |||
cd build | |||
../lib/ant/bin/ant -f build.xml build-testing-drivers | |||
.... | |||
This produces `../aj-build/jars/testing-drivers-all.jar` which you can | |||
@@ -3237,8 +3248,7 @@ http://bugs.eclipse.org/bugs/enter_bug.cgi?product=AJDT ). | |||
Bug reports on ajbrowser should have version information for both Java | |||
and AspectJ, and (most importantly) clear steps for reproducing the bug. | |||
You may submit ajbrowser bugs against the IDE component of AspectJ via | |||
the web form http://bugs.eclipse.org/bugs/enter_bug.cgi?product=AspectJ | |||
. | |||
the web form http://bugs.eclipse.org/bugs/enter_bug.cgi?product=AspectJ. | |||
One of the benefits of open-source is that you can find and fix the bug | |||
for yourself; when you submit the fix back to us, we can validate the | |||
@@ -3422,7 +3432,7 @@ More details for 1.0 and earlier releases are available in changes.html. | |||
*Q:* What is the AspectJ development schedule? | |||
*A:* Below is a table describing the goals for the major releases. For | |||
information about specific features, search the bug database for `RFE`'s | |||
information about specific features, search the bug database for ``RFE``'s | |||
("requests for enhancement") by | |||
http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&bug_severity=enhancement[selecting | |||
severity of "enhancement"]. Like many open-source projects, we don't |
@@ -44,6 +44,7 @@ dump configuration as well as the exception (with stack trace) that is | |||
the source of the problem and any messages issued by the compiler. Most | |||
importantly the exact version of AspectJ is included. | |||
[source, text] | |||
.... | |||
---- AspectJ Properties --- | |||
AspectJ Compiler DEVELOPMENT built on Tuesday Jul 25, 2006 at 13:00:09 GMT | |||
@@ -157,5 +158,4 @@ java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory | |||
at org.aspectj.tools.ajc.Main.run(Main.java:367) | |||
at org.aspectj.tools.ajc.Main.runMain(Main.java:246) | |||
at org.aspectj.tools.ajc.Main.main(Main.java:86) | |||
.... |
@@ -31,6 +31,7 @@ package (and subpackages) but not CGLIB generated classes in the | |||
`com.foo.bar` package (and subpackages). It will also ensure all woven | |||
byte-code is dumped both before and after weaving. | |||
[source, xml] | |||
.... | |||
<aspectj> | |||
<aspects> | |||
@@ -46,6 +47,7 @@ byte-code is dumped both before and after weaving. | |||
You should see messages similar to this: | |||
[source, text] | |||
.... | |||
[WeavingURLClassLoader] info AspectJ Weaver Version 1.5.3 built on Thursday Oct 26, 2006 at 17:22:31 GMT | |||
[WeavingURLClassLoader] info register classloader org.aspectj.weaver.loadtime.WeavingURLClassLoader | |||
@@ -57,6 +59,7 @@ You should see messages similar to this: | |||
On disk you would find the following files: | |||
[source, text] | |||
.... | |||
_ajdump/_before/com/foo/bar/Test.class | |||
_ajdump/com/foo/bar/Test.class |
@@ -103,6 +103,7 @@ during LTW. The following example will produce basic informational | |||
messages about the lifecyle of the weaver in addition to any warning or | |||
error messages. | |||
[source, xml] | |||
.... | |||
<aspectj> | |||
<weaver options="-verbose"> | |||
@@ -116,6 +117,7 @@ defining class loader associated with weaver. You can use this | |||
information in a large system to distinguish between different | |||
applications each of which will typically have its own class loader. | |||
[source, text] | |||
.... | |||
[AppClassLoader@92e78c] info AspectJ Weaver Version 1.5.3 built on Thursday Oct 26, 2006 at 17:22:31 GMT | |||
[AppClassLoader@92e78c] info register classloader sun.misc.Launcher$AppClassLoader@92e78c | |||
@@ -133,6 +135,7 @@ weaving (LTW), why advice has not been woven. Here is a quick guide to | |||
the messages to look for. Firstly if you use the `-verbose` option you | |||
should see the following message when your aspect is registered: | |||
[source, text] | |||
.... | |||
info register aspect MyAspect | |||
.... | |||
@@ -140,6 +143,7 @@ info register aspect MyAspect | |||
Secondly if you use the `-debug` option you should see a message | |||
indicating that you class is being woven: | |||
[source, text] | |||
.... | |||
debug weaving 'HelloWorld' | |||
.... | |||
@@ -150,6 +154,7 @@ determine whether your pointcuts match you can use the `-showWeaveInfo` | |||
option which will cause a message to be issued each time a join point is | |||
woven: | |||
[source, text] | |||
.... | |||
weaveinfo Join point 'method-execution(void HelloWorld.main(java.lang.String[]))' ... | |||
.... |
@@ -82,6 +82,7 @@ Below is an extract from that trace with method arguments removed. You | |||
will notice the millisecond time stamp, thread id and indication of | |||
entry/exit/event or message type for each line of trace. | |||
[source, text] | |||
.... | |||
15:44:18.630 main > org.aspectj.weaver.loadtime.Aj.<init> | |||
15:44:18.660 main < org.aspectj.weaver.loadtime.Aj.<init> | |||
@@ -133,6 +134,7 @@ below could be used to configure Java Logging. The resulting file, just | |||
containing trace for the `org.aspectj.weaver.loadtime` package, will be | |||
written to `java0.log` in your `user.home` directory. | |||
[source, text] | |||
.... | |||
handlers= java.util.logging.FileHandler | |||
@@ -150,6 +152,7 @@ By setting the System property `-Dorg.aspectj.tracing.debug=true` you | |||
should see a message confirming which trace infrastructure is being | |||
used. | |||
[source, text] | |||
.... | |||
TraceFactory.instance=org.aspectj.weaver.tools.Jdk14TraceFactory@12dacd1 | |||
.... |
@@ -7,35 +7,27 @@ This chapter consists entirely of examples of AspectJ use. | |||
The examples can be grouped into four categories: | |||
technique | |||
Examples which illustrate how to use one or more features of the | |||
language. | |||
development | |||
Examples of using AspectJ during the development phase of a project. | |||
production | |||
Examples of using AspectJ to provide functionality in an application. | |||
reusable | |||
Examples of reuse of aspects and pointcuts. | |||
technique:: | |||
Examples which illustrate how to use one or more features of the language | |||
development:: | |||
Examples of using AspectJ during the development phase of a project | |||
production:: | |||
Examples of using AspectJ to provide functionality in an application | |||
reusable:: | |||
Examples of reuse of aspects and pointcuts | |||
[[examples-howto]] | |||
=== Obtaining, Compiling and Running the Examples | |||
The examples source code is part of the AspectJ distribution which may | |||
be downloaded from the AspectJ project page ( | |||
http://eclipse.org/aspectj[] ). | |||
be downloaded from the https://eclipse.org/aspectj[AspectJ project page]. | |||
Compiling most examples is straightforward. Go the `InstallDir/examples` | |||
directory, and look for a `.lst` file in one of the example | |||
subdirectories. Use the `-arglist` option to `ajc` to compile the | |||
example. For instance, to compile the telecom example with billing, type | |||
[source, text] | |||
.... | |||
ajc -argfile telecom/billing.lst | |||
.... | |||
@@ -45,11 +37,13 @@ Java archive (`aspectjrt.jar`). You may either set the `CLASSPATH` | |||
environment variable or use the `-classpath` command line option to the | |||
Java interpreter: | |||
[source, text] | |||
.... | |||
(In Unix use a : in the CLASSPATH) | |||
java -classpath ".:InstallDir/lib/aspectjrt.jar" telecom.billingSimulation | |||
.... | |||
[source, text] | |||
.... | |||
(In Windows use a ; in the CLASSPATH) | |||
java -classpath ".;InstallDir/lib/aspectjrt.jar" telecom.billingSimulation | |||
@@ -64,7 +58,7 @@ dynamic join points and advice, and with static introduction. Advice | |||
changes an application's behavior. Introduction changes both an | |||
application's behavior and its structure. | |||
The first example, xref:#examples-joinPoints[Join Points and ], is about | |||
The first example, xref:#examples-joinPoints[Join Points and `thisJoinPoint`], is about | |||
gathering and using information about the join point that has triggered | |||
some advice. The second example, xref:#examples-roles[Roles and Views], | |||
concerns a crosscutting view of an existing class hierarchy. | |||
@@ -87,6 +81,7 @@ join point. Here, for example, since the only join points picked out by | |||
the pointcut are calls of a certain method, we can get the target value | |||
and one of the argument values of the method calls directly. | |||
[source, java] | |||
.... | |||
before(Point p, int x): target(p) | |||
&& args(x) | |||
@@ -101,6 +96,7 @@ But sometimes the shape of the join point is not so clear. For instance, | |||
suppose a complex application is being debugged, and we want to trace | |||
when any method of some class is executed. The pointcut | |||
[source, java] | |||
.... | |||
pointcut execsInProblemClass(): within(ProblemClass) | |||
&& execution(* *(..)); | |||
@@ -124,19 +120,16 @@ point | |||
* the currently executing object | |||
* the target object | |||
* an object encapsulating the static information about the join point. | |||
This is also available through the special variable | |||
+ | |||
thisJoinPointStaticPart | |||
+ | |||
. | |||
This is also available through the special variable `thisJoinPointStaticPart`. | |||
===== The `Demo` class | |||
The class `tjp.Demo` in `tjp/Demo.java` defines two methods `foo` and | |||
`bar` with different parameter lists and return types. Both are called, | |||
with suitable arguments, by `Demo`'s `go` method which was invoked from | |||
with suitable arguments, by ``Demo``'s `go` method which was invoked from | |||
within its `main` method. | |||
[source, java] | |||
.... | |||
public class Demo { | |||
static Demo d; | |||
@@ -168,6 +161,7 @@ This aspect uses around advice to intercept the execution of methods | |||
`foo` and `bar` in `Demo`, and prints out information garnered from | |||
`thisJoinPoint` to the console. | |||
[source, java] | |||
.... | |||
aspect GetInfo { | |||
@@ -207,6 +201,7 @@ aspect GetInfo { | |||
The pointcut `goCut` is defined as | |||
[source, java] | |||
.... | |||
cflow(this(Demo)) && execution(void go()) | |||
.... | |||
@@ -221,7 +216,7 @@ advised. | |||
The name of the method and that method's defining class are available as | |||
parts of the | |||
xref:../api/org/aspectj/lang/Signature.html[org.aspectj.lang.Signature] | |||
xref:../api/org/aspectj/lang/Signature.html[`org.aspectj.lang.Signature`] | |||
object returned by calling `getSignature()` on either `thisJoinPoint` or | |||
`thisJoinPointStaticPart`. | |||
@@ -274,7 +269,7 @@ are provided by AspectJ without having to modify the code for the class | |||
The `Point` class defines geometric points whose interface includes | |||
polar and rectangular coordinates, plus some simple operations to | |||
relocate points. `Point`'s implementation has attributes for both its | |||
relocate points. ``Point``'s implementation has attributes for both its | |||
polar and rectangular coordinates, plus flags to indicate which | |||
currently reflect the position of the point. Some operations cause the | |||
polar coordinates to be updated from the rectangular, and some have the | |||
@@ -292,20 +287,21 @@ image:aspects.gif[image] | |||
===== The `CloneablePoint` aspect | |||
This first aspect is responsible for `Point`'s implementation of the | |||
This first aspect is responsible for ``Point``'s implementation of the | |||
`Cloneable` interface. It declares that `Point implements Cloneable` | |||
with a `declare parents` form, and also publically declares a | |||
specialized `Point`'s `clone()` method. In Java, all objects inherit the | |||
specialized ``Point``'s `clone()` method. In Java, all objects inherit the | |||
method `clone` from the class `Object`, but an object is not cloneable | |||
unless its class also implements the interface `Cloneable`. In addition, | |||
classes frequently have requirements over and above the simple | |||
bit-for-bit copying that `Object.clone` does. In our case, we want to | |||
update a `Point`'s coordinate systems before we actually clone the | |||
update a ``Point``'s coordinate systems before we actually clone the | |||
`Point`. So our aspect makes sure that `Point` overrides `Object.clone` | |||
with a new method that does what we want. | |||
We also define a test `main` method in the aspect for convenience. | |||
[source, java] | |||
.... | |||
public aspect CloneablePoint { | |||
@@ -338,7 +334,7 @@ public aspect CloneablePoint { | |||
===== The `ComparablePoint` aspect | |||
`ComparablePoint` is responsible for `Point`'s implementation of the | |||
`ComparablePoint` is responsible for ``Point``'s implementation of the | |||
`Comparable` interface. | |||
The interface `Comparable` defines the single method `compareTo` which | |||
@@ -349,11 +345,11 @@ class that implement it. | |||
parents` to declare that `Point implements | |||
Comparable`, and also publically declares the appropriate | |||
`compareTo(Object)` method: A `Point` `p1` is said to be less than | |||
another `Point`` | |||
p2` if `p1` is closer to the origin. | |||
another `Point p2` if `p1` is closer to the origin. | |||
We also define a test `main` method in the aspect for convenience. | |||
[source, java] | |||
.... | |||
public aspect ComparablePoint { | |||
@@ -391,8 +387,8 @@ public aspect ComparablePoint { | |||
===== The `HashablePoint` aspect | |||
Our third aspect is responsible for `Point`'s overriding of `Object`'s | |||
`equals` and `hashCode` methods in order to make `Point`s hashable. | |||
Our third aspect is responsible for ``Point``'s overriding of ``Object``'s | |||
`equals` and `hashCode` methods in order to make ``Point``s hashable. | |||
The method `Object.hashCode` returns an integer, suitable for use as a | |||
hash table key. It is not required that two objects which are not equal | |||
@@ -408,14 +404,15 @@ values, or the same `rho` and `theta` values, not just when they refer | |||
to the same object. We do this by overriding the methods `equals` and | |||
`hashCode` in the class `Point`. | |||
So `HashablePoint` declares `Point`'s `hashCode` and `equals` methods, | |||
using `Point`'s rectangular coordinates to generate a hash code and to | |||
So `HashablePoint` declares ``Point``'s `hashCode` and `equals` methods, | |||
using ``Point``'s rectangular coordinates to generate a hash code and to | |||
test for equality. The `x` and `y` coordinates are obtained using the | |||
appropriate get methods, which ensure the rectangular coordinates are | |||
up-to-date before returning their values. | |||
And again, we supply a `main` method in the aspect for testing. | |||
[source, java] | |||
.... | |||
public aspect HashablePoint { | |||
@@ -489,6 +486,7 @@ Throughout this example we will use a simple application that contains | |||
only four classes. The application is about shapes. The `TwoDShape` | |||
class is the root of the shape hierarchy: | |||
[source, java] | |||
.... | |||
public abstract class TwoDShape { | |||
protected double x, y; | |||
@@ -512,6 +510,7 @@ public abstract class TwoDShape { | |||
`TwoDShape` has two subclasses, `Circle` and `Square`: | |||
[source, java] | |||
.... | |||
public class Circle extends TwoDShape { | |||
protected double r; | |||
@@ -533,6 +532,7 @@ public class Circle extends TwoDShape { | |||
} | |||
.... | |||
[source, java] | |||
.... | |||
public class Square extends TwoDShape { | |||
protected double s; // side | |||
@@ -558,12 +558,14 @@ To run this application, compile the classes. You can do it with or | |||
without ajc, the AspectJ compiler. If you've installed AspectJ, go to | |||
the directory `InstallDir/examples` and type: | |||
[source, text] | |||
.... | |||
ajc -argfile tracing/notrace.lst | |||
.... | |||
To run the program, type | |||
[source, text] | |||
.... | |||
java tracing.ExampleMain | |||
.... | |||
@@ -571,6 +573,7 @@ java tracing.ExampleMain | |||
(we don't need anything special on the classpath since this is pure Java | |||
code). You should see the following output: | |||
[source, text] | |||
.... | |||
c1.perimeter() = 12.566370614359172 | |||
c1.area() = 12.566370614359172 | |||
@@ -588,6 +591,7 @@ by writing a `Trace` class that is exactly what we would write if we | |||
didn't have aspects. The implementation is in `version1/Trace.java`. Its | |||
public interface is: | |||
[source, java] | |||
.... | |||
public class Trace { | |||
public static int TRACELEVEL = 0; | |||
@@ -605,8 +609,9 @@ calls, and we would hope we had not forgotten any method. But we can do | |||
that more consistently and reliably with the following aspect (found in | |||
`version1/TraceMyClasses.java`): | |||
[source, java] | |||
.... | |||
aspect TraceMyClasses { | |||
public aspect TraceMyClasses { | |||
pointcut myClass(): within(TwoDShape) || within(Circle) || within(Square); | |||
pointcut myConstructor(): myClass() && execution(new(..)); | |||
pointcut myMethod(): myClass() && execution(* *(..)); | |||
@@ -638,6 +643,7 @@ information, we can get it through `thisJoinPointStaticPart`. | |||
To run this version of tracing, go to the directory | |||
`InstallDir/examples` and type: | |||
[source, text] | |||
.... | |||
ajc -argfile tracing/tracev1.lst | |||
.... | |||
@@ -645,6 +651,7 @@ ajc -argfile tracing/tracev1.lst | |||
Running the main method of `tracing.version1.TraceMyClasses` should | |||
produce the output: | |||
[source, text] | |||
.... | |||
--> tracing.TwoDShape(double, double) | |||
<-- tracing.TwoDShape(double, double) | |||
@@ -707,6 +714,7 @@ functionality of `Trace - version1` with the crosscutting support of | |||
`TraceMyClasses - version1`. We end up with a `Trace` aspect (found in | |||
`version2/Trace.java`) with the following public interface | |||
[source, java] | |||
.... | |||
abstract aspect Trace { | |||
@@ -721,6 +729,7 @@ abstract aspect Trace { | |||
In order to use it, we need to define our own subclass that knows about | |||
our application classes, in `version2/TraceMyClasses.java`: | |||
[source, java] | |||
.... | |||
public aspect TraceMyClasses extends Trace { | |||
pointcut myClass(): within(TwoDShape) || within(Circle) || within(Square); | |||
@@ -737,6 +746,7 @@ Notice that we've simply made the pointcut `classes`, that was an | |||
abstract pointcut in the super-aspect, concrete. To run this version of | |||
tracing, go to the directory `examples` and type: | |||
[source, text] | |||
.... | |||
ajc -argfile tracing/tracev2.lst | |||
.... | |||
@@ -748,6 +758,7 @@ the same trace information as that from version 1. | |||
The entire implementation of the new `Trace` class is: | |||
[source, java] | |||
.... | |||
abstract aspect Trace { | |||
@@ -869,6 +880,7 @@ bound property protocol. | |||
The `Point` class is a very simple class with trivial getters and | |||
setters, and a simple vector offset method. | |||
[source, java] | |||
.... | |||
class Point { | |||
@@ -908,11 +920,12 @@ class Point { | |||
===== The `BoundPoint` aspect | |||
The `BoundPoint` aspect is responsible for `Point`'s "beanness". The | |||
The `BoundPoint` aspect is responsible for ``Point``'s "beanness". The | |||
first thing it does is privately declare that each `Point` has a | |||
`support` field that holds reference to an instance of | |||
`PropertyChangeSupport`. | |||
[source, java] | |||
.... | |||
private PropertyChangeSupport Point.support = new PropertyChangeSupport(this); | |||
.... | |||
@@ -923,10 +936,11 @@ passing it `this`, an instance of `Point`. Since the `support` field is | |||
private declared in the aspect, only the code in the aspect can refer to | |||
it. | |||
The aspect also declares `Point`'s methods for registering and managing | |||
The aspect also declares ``Point``'s methods for registering and managing | |||
listeners for property change events, which delegate the work to the | |||
property change support object: | |||
[source, java] | |||
.... | |||
public void Point.addPropertyChangeListener(PropertyChangeListener listener){ | |||
support.addPropertyChangeListener(listener); | |||
@@ -951,6 +965,7 @@ public void Point.hasListeners(String propertyName) { | |||
The aspect is also responsible for making sure `Point` implements the | |||
`Serializable` interface: | |||
[source, java] | |||
.... | |||
declare parents: Point implements Serializable; | |||
.... | |||
@@ -959,13 +974,14 @@ Implementing this interface in Java does not require any methods to be | |||
implemented. Serialization for `Point` objects is provided by the | |||
default serialization method. | |||
The `setters` pointcut picks out calls to the `Point`'s `set` methods: | |||
The `setters` pointcut picks out calls to the ``Point``'s `set` methods: | |||
any method whose name begins with "`set`" and takes one parameter. The | |||
around advice on `setters()` stores the values of the `X` and `Y` | |||
properties, calls the original `set` method and then fires the | |||
appropriate property change event according to which set method was | |||
called. | |||
[source, java] | |||
.... | |||
aspect BoundPoint { | |||
private PropertyChangeSupport Point.support = new PropertyChangeSupport(this); | |||
@@ -1025,6 +1041,7 @@ that point: calling its set methods and the offset method. Then it | |||
serializes the point and writes it to a file and then reads it back. The | |||
result of saving and restoring the point is that a new point is created. | |||
[source, java] | |||
.... | |||
class Demo implements PropertyChangeListener { | |||
@@ -1059,6 +1076,7 @@ class Demo implements PropertyChangeListener { | |||
To compile and run this example, go to the examples directory and type: | |||
[source, text] | |||
.... | |||
ajc -argfile bean/files.lst | |||
java bean.Demo | |||
@@ -1093,6 +1111,7 @@ The generic parts of the protocol are the interfaces `Subject` and | |||
view `Observer` objects, and a method for getting data about state | |||
changes: | |||
[source, java] | |||
.... | |||
interface Subject { | |||
void addObserver(Observer obs); | |||
@@ -1105,6 +1124,7 @@ interface Subject { | |||
The `Observer` interface is just as simple, with methods to set and get | |||
`Subject` objects, and a method to call when the subject gets updated. | |||
[source, java] | |||
.... | |||
interface Observer { | |||
void setSubject(Subject s); | |||
@@ -1117,6 +1137,7 @@ The `SubjectObserverProtocol` aspect contains within it all of the | |||
generic parts of the protocol, namely, how to fire the `Observer` | |||
objects' update methods when some state changes in a subject. | |||
[source, java] | |||
.... | |||
abstract aspect SubjectObserverProtocol { | |||
@@ -1157,6 +1178,7 @@ its `Subject`. | |||
`Button` objects extend `java.awt.Button`, and all they do is make sure | |||
the `void click()` method is called whenever a button is clicked. | |||
[source, java] | |||
.... | |||
class Button extends java.awt.Button { | |||
@@ -1187,6 +1209,7 @@ Note that this class knows nothing about being a Subject. | |||
ColorLabel objects are labels that support the void colorCycle() method. | |||
Again, they know nothing about being an observer. | |||
[source, java] | |||
.... | |||
class ColorLabel extends Label { | |||
@@ -1212,6 +1235,7 @@ Finally, the `SubjectObserverProtocolImpl` implements the | |||
subject/observer protocol, with `Button` objects as subjects and | |||
`ColorLabel` objects as observers: | |||
[source, java] | |||
.... | |||
package observer; | |||
@@ -1246,6 +1270,7 @@ all `ColorLabel` objects observing that button will `colorCycle`. | |||
buttons and three observers and links them together as subjects and | |||
observers. So to run the demo, go to the `examples` directory and type: | |||
[source, text] | |||
.... | |||
ajc -argfile observer/files.lst | |||
java observer.Demo | |||
@@ -1303,6 +1328,7 @@ involved in many calls at one time. image:telecom.gif[image] | |||
`Customer` has methods `call`, `pickup`, `hangup` and `merge` for | |||
managing calls. | |||
[source, java] | |||
.... | |||
public class Customer { | |||
@@ -1377,6 +1403,7 @@ connection between customers. It does this with a simple state machine | |||
connections can be observed. Connection is an abstract class with two | |||
concrete subclasses: `Local` and `LongDistance`. | |||
[source, java] | |||
.... | |||
abstract class Connection { | |||
@@ -1422,6 +1449,7 @@ abstract class Connection { | |||
The two kinds of connections supported by our simulation are `Local` and | |||
`LongDistance` connections. | |||
[source, java] | |||
.... | |||
class Local extends Connection { | |||
Local(Customer a, Customer b) { | |||
@@ -1432,6 +1460,7 @@ class Local extends Connection { | |||
} | |||
.... | |||
[source, java] | |||
.... | |||
class LongDistance extends Connection { | |||
LongDistance(Customer a, Customer b) { | |||
@@ -1448,6 +1477,7 @@ The source files for the basic system are listed in the file | |||
`basic.lst`. To build and run the basic system, in a shell window, type | |||
these commands: | |||
[source, text] | |||
.... | |||
ajc -argfile telecom/basic.lst | |||
java telecom.BasicSimulation | |||
@@ -1466,6 +1496,7 @@ stopped, and returns their difference when asked for the elapsed time. | |||
The aspect `TimerLog` (below) can be used to cause the start and stop | |||
times to be printed to standard output. | |||
[source, java] | |||
.... | |||
class Timer { | |||
long startTime, stopTime; | |||
@@ -1490,6 +1521,7 @@ class Timer { | |||
The `TimerLog` aspect can be included in a build to get the timer to | |||
announce when it is started and stopped. | |||
[source, java] | |||
.... | |||
public aspect TimerLog { | |||
@@ -1509,6 +1541,7 @@ The `Timing` aspect is declares an inter-type field `totalConnectTime` | |||
for `Customer` to store the accumulated connection time per `Customer`. | |||
It also declares that each `Connection` object has a timer. | |||
[source, java] | |||
.... | |||
public long Customer.totalConnectTime = 0; | |||
private Timer Connection.timer = new Timer(); | |||
@@ -1518,6 +1551,7 @@ Two pieces of after advice ensure that the timer is started when a | |||
connection is completed and and stopped when it is dropped. The pointcut | |||
`endTiming` is defined so that it can be used by the `Billing` aspect. | |||
[source, java] | |||
.... | |||
public aspect Timing { | |||
@@ -1556,10 +1590,11 @@ responsible to pay for it. It also declares the inter-type method | |||
charged differently. The call charge must be calculated after the timer | |||
is stopped; the after advice on pointcut `Timing.endTiming` does this, | |||
and `Billing` is declared to be more precedent than `Timing` to make | |||
sure that this advice runs after `Timing`'s advice on the same join | |||
sure that this advice runs after ``Timing``'s advice on the same join | |||
point. Finally, it declares inter-type methods and fields for `Customer` | |||
to handle the `totalCharge`. | |||
[source, java] | |||
.... | |||
public aspect Billing { | |||
// precedence required to get advice on endtiming in the right order | |||
@@ -1613,6 +1648,7 @@ the method run of the superclass `AbstractSimulation`. This method is | |||
intended to print out the status of the customer, with respect to the | |||
`Timing` feature. | |||
[source, java] | |||
.... | |||
protected void report(Customer c){ | |||
Timing t = Timing.aspectOf(); | |||
@@ -1626,6 +1662,7 @@ The files timing.lst and billing.lst contain file lists for the timing | |||
and billing configurations. To build and run the application with only | |||
the timing feature, go to the directory examples and type: | |||
[source, text] | |||
.... | |||
ajc -argfile telecom/timing.lst | |||
java telecom.TimingSimulation | |||
@@ -1634,6 +1671,7 @@ java telecom.TimingSimulation | |||
To build and run the application with the timing and billing features, | |||
go to the directory examples and type: | |||
[source, text] | |||
.... | |||
ajc -argfile telecom/billing.lst | |||
java telecom.BillingSimulation | |||
@@ -1669,6 +1707,7 @@ the object whose methods are being traced. This can be achieved in at | |||
least two ways. One way is keep the interface of the methods | |||
`traceEntry` and `traceExit` as it was before, | |||
[source, java] | |||
.... | |||
public static void traceEntry(String str); | |||
public static void traceExit(String str); | |||
@@ -1678,6 +1717,7 @@ In this case, the caller is responsible for ensuring that the string | |||
representation of the object is part of the string given as argument. | |||
So, calls must look like: | |||
[source, java] | |||
.... | |||
Trace.traceEntry("Square.distance in " + toString()); | |||
.... | |||
@@ -1685,6 +1725,7 @@ Trace.traceEntry("Square.distance in " + toString()); | |||
Another way is to enforce the requirement with a second argument in the | |||
trace operations, e.g. | |||
[source, java] | |||
.... | |||
public static void traceEntry(String str, Object obj); | |||
public static void traceExit(String str, Object obj); | |||
@@ -1694,6 +1735,7 @@ In this case, the caller is still responsible for sending the right | |||
object, but at least there is some guarantees that some object will be | |||
passed. The calls will look like: | |||
[source, java] | |||
.... | |||
Trace.traceEntry("Square.distance", this); | |||
.... | |||
@@ -1709,6 +1751,7 @@ only a small effect inside the `Trace` class. Here's a partial view at | |||
the implementation of `Trace`, version 3. The differences with respect | |||
to version 2 are stressed in the comments: | |||
[source, java] | |||
.... | |||
abstract aspect Trace { | |||
@@ -1794,6 +1837,7 @@ In fact, esimply excluding the execution join point may not be enough, | |||
if there are calls to other traced methods within it -- in which case, | |||
the restriction should be | |||
[source, java] | |||
.... | |||
&& !cflow(execution(String toString())) | |||
.... | |||
@@ -1811,6 +1855,7 @@ every application class. | |||
Finally, to run this version of tracing, go to the directory `examples` | |||
and type: | |||
[source, text] | |||
.... | |||
ajc -argfile tracing/tracev3.lst | |||
.... | |||
@@ -1819,12 +1864,14 @@ The file tracev3.lst lists the application classes as well as this | |||
version of the files `Trace.java` and `TraceMyClasses.java`. To run the | |||
program, type | |||
[source, text] | |||
.... | |||
java tracing.version3.TraceMyClasses | |||
.... | |||
The output should be: | |||
[source, text] | |||
.... | |||
--> tracing.TwoDShape(double, double) | |||
<-- tracing.TwoDShape(double, double) |
@@ -39,7 +39,7 @@ testing and performance tuning of applications. And, in the section | |||
following, xref:#starting-production[Production Aspects], we present | |||
aspects that implement crosscutting functionality common in Java | |||
applications. We will defer discussing a third category of aspects, | |||
reusable aspects, until xref:language.adoc[The AspectJ Language]. | |||
reusable aspects, until xref:language.adoc#language[The AspectJ Language]. | |||
These categories are informal, and this ordering is not the only way to | |||
adopt AspectJ. Some developers may want to use a production aspect right | |||
@@ -56,7 +56,7 @@ language, but this is by no means a complete overview of AspectJ. | |||
The features are presented using a simple figure editor system. A | |||
`Figure` consists of a number of `FigureElements`, which can be either | |||
`Point`s or `Line`s. The `Figure` class provides factory services. There | |||
``Point``s or ``Line``s. The `Figure` class provides factory services. There | |||
is also a `Display`. Most example programs later in this chapter are | |||
based on this system as well. | |||
@@ -143,17 +143,19 @@ context_ of the original call join point. | |||
In AspectJ, _pointcuts_ pick out certain join points in the program | |||
flow. For example, the pointcut | |||
[source, java] | |||
.... | |||
call(void Point.setX(int)) | |||
.... | |||
picks out each join point that is a call to a method that has the | |||
signature `void Point.setX(int)` - that is, `Point`'s void `setX` method | |||
signature `void Point.setX(int)` - that is, ``Point``'s void `setX` method | |||
with a single `int` parameter. | |||
A pointcut can be built out of other pointcuts with and, or, and not | |||
(spelled `&&`, `||`, and `!`). For example: | |||
[source, java] | |||
.... | |||
call(void Point.setX(int)) || | |||
call(void Point.setY(int)) | |||
@@ -165,6 +167,7 @@ picks out each join point that is either a call to `setX` or a call to | |||
Pointcuts can identify join points from many different types - in other | |||
words, they can crosscut types. For example, | |||
[source, java] | |||
.... | |||
call(void FigureElement.setXY(int,int)) || | |||
call(void Point.setX(int)) || | |||
@@ -182,6 +185,7 @@ crosscutting concern, it is a bit of a mouthful. So AspectJ allows | |||
programmers to define their own named pointcuts with the `pointcut` | |||
form. So the following declares a new, named pointcut: | |||
[source, java] | |||
.... | |||
pointcut move(): | |||
call(void FigureElement.setXY(int,int)) || | |||
@@ -202,6 +206,7 @@ _property-based_ crosscutting. The simplest of these involve using | |||
wildcards in certain fields of the method signature. For example, the | |||
pointcut | |||
[source, java] | |||
.... | |||
call(void Figure.make*(..)) | |||
.... | |||
@@ -211,16 +216,18 @@ picks out each join point that's a call to a void method defined on | |||
parameters. In our system, this picks out calls to the factory methods | |||
`makePoint` and `makeLine`. The pointcut | |||
[source, java] | |||
.... | |||
call(public * Figure.* (..)) | |||
.... | |||
picks out each call to `Figure`'s public methods. | |||
picks out each call to ``Figure``'s public methods. | |||
But wildcards aren't the only properties AspectJ supports. Another | |||
pointcut, `cflow`, identifies join points based on whether they occur in | |||
the dynamic context of other join points. So | |||
[source, java] | |||
.... | |||
cflow(move()) | |||
.... | |||
@@ -245,6 +252,7 @@ For example, before advice on a method call join point runs before the | |||
actual method starts running, just after the arguments to the method | |||
call are evaluated. | |||
[source, java] | |||
.... | |||
before(): move() { | |||
System.out.println("about to move"); | |||
@@ -260,6 +268,7 @@ of after advice: `after returning`, `after | |||
throwing`, and plain `after` (which runs after returning _or_ | |||
throwing, like Java's `finally`). | |||
[source, java] | |||
.... | |||
after() returning: move() { | |||
System.out.println("just successfully moved"); | |||
@@ -280,6 +289,7 @@ An advice declaration has a parameter list (like a method) that gives | |||
names to all the pieces of context that it uses. For example, the after | |||
advice | |||
[source, java] | |||
.... | |||
after(FigureElement fe, int x, int y) returning: | |||
...SomePointcut... { | |||
@@ -288,10 +298,11 @@ after(FigureElement fe, int x, int y) returning: | |||
.... | |||
uses three pieces of exposed context, a `FigureElement` named fe, and | |||
two `int`s named x and y. | |||
two ``int``s named x and y. | |||
The body of the advice uses the names just like method parameters, so | |||
[source, java] | |||
.... | |||
after(FigureElement fe, int x, int y) returning: | |||
...SomePointcut... { | |||
@@ -303,6 +314,7 @@ The advice's pointcut publishes the values for the advice's arguments. | |||
The three primitive pointcuts `this`, `target` and `args` are used to | |||
publish these values. So now we can write the complete piece of advice: | |||
[source, java] | |||
.... | |||
after(FigureElement fe, int x, int y) returning: | |||
call(void FigureElement.setXY(int, int)) | |||
@@ -326,6 +338,7 @@ named pointcut is used (by advice, or in another named pointcut), it | |||
publishes its context by name just like the `this`, `target` and `args` | |||
pointcut. So another way to write the above advice is | |||
[source, java] | |||
.... | |||
pointcut setXY(FigureElement fe, int x, int y): | |||
call(void FigureElement.setXY(int, int)) | |||
@@ -360,8 +373,9 @@ Suppose we want to have `Screen` objects observe changes to `Point` | |||
objects, where `Point` is an existing class. We can implement this by | |||
writing an aspect declaring that the class Point `Point` has an instance | |||
field, `observers`, that keeps track of the `Screen` objects that are | |||
observing `Point`s. | |||
observing ``Point``s. | |||
[source, java] | |||
.... | |||
aspect PointObserving { | |||
private Vector Point.observers = new Vector(); | |||
@@ -373,6 +387,7 @@ The `observers` field is private, so only `PointObserving` can see it. | |||
So observers are added or removed with the static methods `addObserver` | |||
and `removeObserver` on the aspect. | |||
[source, java] | |||
.... | |||
aspect PointObserving { | |||
private Vector Point.observers = new Vector(); | |||
@@ -391,6 +406,7 @@ Along with this, we can define a pointcut `changes` that defines what we | |||
want to observe, and the after advice defines what we want to do when we | |||
observe a change. | |||
[source, java] | |||
.... | |||
aspect PointObserving { | |||
private Vector Point.observers = new Vector(); | |||
@@ -417,7 +433,7 @@ aspect PointObserving { | |||
} | |||
.... | |||
Note that neither `Screen`'s nor `Point`'s code has to be modified, and | |||
Note that neither ``Screen``'s nor ``Point``'s code has to be modified, and | |||
that all the changes needed to support this new capability are local to | |||
this aspect. | |||
@@ -435,6 +451,7 @@ aspect instances. By default, each aspect is a singleton, so one aspect | |||
instance is created. This means that advice may use non-static fields of | |||
the aspect, if it needs to keep state around: | |||
[source, java] | |||
.... | |||
aspect Logging { | |||
OutputStream logStream = System.err; | |||
@@ -471,6 +488,7 @@ workings of a program. It is a simple tracing aspect that prints a | |||
message at specified method calls. In our figure editor example, one | |||
such aspect might simply trace whenever points are drawn. | |||
[source, java] | |||
.... | |||
aspect SimpleTracing { | |||
pointcut tracedCall(): | |||
@@ -487,6 +505,7 @@ advice bodies this variable is bound to an object that describes the | |||
current join point. The effect of this code is to print a line like the | |||
following every time a figure element receives a `draw` method call: | |||
[source, text] | |||
.... | |||
Entering: call(void FigureElement.draw(GraphicsContext)) | |||
.... | |||
@@ -529,6 +548,7 @@ For example, the following aspect counts the number of calls to the | |||
methods of a `Point` that happen within the control flow of those calls | |||
to `rotate`: | |||
[source, java] | |||
.... | |||
aspect SetsInRotateCounting { | |||
int rotateCount = 0; | |||
@@ -589,6 +609,7 @@ properly do the work they are supposed to. | |||
AspectJ makes it possible to implement pre- and post-condition testing | |||
in modular form. For example, this code | |||
[source, java] | |||
.... | |||
aspect PointBoundsChecking { | |||
@@ -636,6 +657,7 @@ the constraint that only the well-known factory methods can add an | |||
element to the registry of figure elements. Enforcing this constraint | |||
ensures that no figure element is added to the registry more than once. | |||
[source, java] | |||
.... | |||
aspect RegistrationProtection { | |||
@@ -662,6 +684,7 @@ This advice throws a runtime exception at certain join points, but | |||
AspectJ can do better. Using the `declare error` form, we can have the | |||
_compiler_ signal the error. | |||
[source, java] | |||
.... | |||
aspect RegistrationProtection { | |||
@@ -722,6 +745,7 @@ state of the dirty flag and resets it to false. The pointcut `move` | |||
captures all the method calls that can move a figure element. The after | |||
advice on `move` sets the dirty flag whenever an object moves. | |||
[source, java] | |||
.... | |||
aspect MoveTracking { | |||
private static boolean dirty = false; | |||
@@ -807,6 +831,7 @@ modular way. The following code adds after advice that runs only when | |||
the factory methods of `Figure` are called in the control flow of a | |||
method on a `ColorControllingClient`. | |||
[source, java] | |||
.... | |||
aspect ColorControl { | |||
pointcut CCClientCflow(ColorControllingClient client): | |||
@@ -841,6 +866,7 @@ captures the public method calls of the package, and the after advice | |||
runs whenever one of those calls throws an Error. The advice logs that | |||
Error and then the throw resumes. | |||
[source, java] | |||
.... | |||
aspect PublicErrorLogging { | |||
Log log = new Log(); | |||
@@ -861,6 +887,7 @@ outermost call into the `com.bigboxco` package and the re-entrant call. | |||
The `cflow` primitive pointcut can be used in a nice way to exclude | |||
these re-entrant calls: | |||
[source, java] | |||
.... | |||
after() throwing (Error e): | |||
publicMethodCall() && !cflow(publicMethodCall()) { | |||
@@ -874,6 +901,7 @@ individual methods handle each of the different kinds of elements that | |||
must be parsed. They have names like `parseMethodDec`, `parseThrows`, | |||
and `parseExpr`. | |||
[source, java] | |||
.... | |||
aspect ContextFilling { | |||
pointcut parse(JavaParser jp): |
@@ -11,6 +11,7 @@ Here's an example of how to enfore a rule that code in the java.sql | |||
package can only be used from one particular package in your system. | |||
This doesn't require any access to code in the java.sql package. | |||
[source, java] | |||
.... | |||
/* Any call to methods or constructors in java.sql */ | |||
pointcut restrictedCall(): | |||
@@ -27,6 +28,7 @@ declare error: restrictedCall() && illegalSource(): | |||
Any call to an instance of a subtype of AbstractFacade whose class is | |||
not exactly equal to AbstractFacade: | |||
[source, java] | |||
.... | |||
pointcut nonAbstract(AbstractFacade af): | |||
call(* *(..)) | |||
@@ -37,6 +39,7 @@ pointcut nonAbstract(AbstractFacade af): | |||
If AbstractFacade is an abstract class or an interface, then every | |||
instance must be of a subtype and you can replace this with: | |||
[source, java] | |||
.... | |||
pointcut nonAbstract(AbstractFacade af): | |||
call(* *(..)) | |||
@@ -46,6 +49,7 @@ pointcut nonAbstract(AbstractFacade af): | |||
Any call to a method which is defined by a subtype of AbstractFacade, | |||
but which isn't defined by the type AbstractFacade itself: | |||
[source, java] | |||
.... | |||
pointcut callToUndefinedMethod(): | |||
call(* AbstractFacade+.*(..)) | |||
@@ -55,6 +59,7 @@ pointcut callToUndefinedMethod(): | |||
The execution of a method that is defined in the source code for a type | |||
that is a subtype of AbstractFacade but not in AbstractFacade itself: | |||
[source, java] | |||
.... | |||
pointcut executionOfUndefinedMethod(): | |||
execution(* *(..)) |
@@ -17,6 +17,7 @@ implementations should do tomorrow. | |||
According to the AspectJ language semantics, the declaration | |||
[source, java] | |||
.... | |||
before(): get(int Point.x) { System.out.println("got x"); } | |||
.... | |||
@@ -128,6 +129,7 @@ source code. This means that there may be call join points to | |||
`Class.forName` or `StringBuffer.append` from programs that do not, at | |||
first glance, appear to contain such calls: | |||
[source, java] | |||
.... | |||
class Test { | |||
void main(String[] args) { | |||
@@ -158,6 +160,7 @@ be the case. Before advice is allowed. | |||
The second is that the control flow of a handler join point is not | |||
picked out. For example, the following pointcut | |||
[source, java] | |||
.... | |||
cflow(call(void foo()) || handler(java.io.IOException)) | |||
.... | |||
@@ -173,6 +176,7 @@ This does not restrict programs from placing before advice on handlers | |||
inside _other_ control flows. This advice, for example, is perfectly | |||
fine: | |||
[source, java] | |||
.... | |||
before(): handler(java.io.IOException) && cflow(void parse()) { | |||
System.out.println("about to handle an exception while parsing"); | |||
@@ -187,6 +191,7 @@ have fewer such restrictions. | |||
The code for Java initializers, such as the assignment to the field d in | |||
[source, java] | |||
.... | |||
class C { | |||
double d = Math.sqrt(2); | |||
@@ -203,6 +208,7 @@ a super-constructor (as opposed to a `this` constructor), the target | |||
type's initialization code will _not_ be run when that inter-type | |||
constructor is called. | |||
[source, java] | |||
.... | |||
aspect A { | |||
C.new(Object o) {} // implicitly calls super() |
@@ -24,30 +24,31 @@ exposed to the new terminology introduced by AspectJ. | |||
Here's an example of an aspect definition in AspectJ: | |||
.... | |||
1 aspect FaultHandler { | |||
2 | |||
3 private boolean Server.disabled = false; | |||
4 | |||
5 private void reportFault() { | |||
6 System.out.println("Failure! Please fix it."); | |||
7 } | |||
8 | |||
9 public static void fixServer(Server s) { | |||
10 s.disabled = false; | |||
11 } | |||
12 | |||
13 pointcut services(Server s): target(s) && call(public * *(..)); | |||
14 | |||
15 before(Server s): services(s) { | |||
16 if (s.disabled) throw new DisabledException(); | |||
17 } | |||
18 | |||
19 after(Server s) throwing (FaultException e): services(s) { | |||
20 s.disabled = true; | |||
21 reportFault(); | |||
22 } | |||
23 } | |||
[source, java] | |||
.... | |||
/*01*/ aspect FaultHandler { | |||
/*02*/ | |||
/*03*/ private boolean Server.disabled = false; | |||
/*04*/ | |||
/*05*/ private void reportFault() { | |||
/*06*/ System.out.println("Failure! Please fix it."); | |||
/*07*/ } | |||
/*08*/ | |||
/*09*/ public static void fixServer(Server s) { | |||
/*10*/ s.disabled = false; | |||
/*11*/ } | |||
/*12*/ | |||
/*13*/ pointcut services(Server s): target(s) && call(public * *(..)); | |||
/*14*/ | |||
/*15*/ before(Server s): services(s) { | |||
/*16*/ if (s.disabled) throw new DisabledException(); | |||
/*17*/ } | |||
/*18*/ | |||
/*19*/ after(Server s) throwing (FaultException e): services(s) { | |||
/*20*/ s.disabled = true; | |||
/*21*/ reportFault(); | |||
/*22*/ } | |||
/*23*/ } | |||
.... | |||
The `FaultHandler` consists of one inter-type field on `Server` (line | |||
@@ -69,6 +70,7 @@ invocations and executions, the handling of exceptions, field | |||
assignments and accesses, etc. Take, for example, the pointcut | |||
definition in line 13: | |||
[source, java] | |||
.... | |||
pointcut services(Server s): target(s) && call(public * *(..)) | |||
.... | |||
@@ -114,6 +116,7 @@ define aspect implementation that runs at join points picked out by the | |||
pointcut. For example, the advice in lines 15-17 specifies that the | |||
following piece of code | |||
[source, java] | |||
.... | |||
{ | |||
if (s.disabled) throw new DisabledException(); | |||
@@ -128,6 +131,7 @@ corresponding methods are executed. | |||
The advice in lines 19-22 defines another piece of implementation that | |||
is executed on the same pointcut: | |||
[source, java] | |||
.... | |||
{ | |||
s.disabled = true; | |||
@@ -148,6 +152,7 @@ this guide. | |||
Consider the following Java class: | |||
[source, java] | |||
.... | |||
class Point { | |||
private int x, y; | |||
@@ -166,6 +171,7 @@ In order to get an intuitive understanding of AspectJ's join points and | |||
pointcuts, let's go back to some of the basic principles of Java. | |||
Consider the following a method declaration in class Point: | |||
[source, java] | |||
.... | |||
void setX(int x) { this.x = x; } | |||
.... | |||
@@ -192,6 +198,7 @@ complete listing.) | |||
Pointcuts pick out these join points. For example, the pointcut | |||
[source, java] | |||
.... | |||
pointcut setter(): target(Point) && | |||
(call(void setX(int)) || | |||
@@ -201,6 +208,7 @@ pointcut setter(): target(Point) && | |||
picks out each call to `setX(int)` or `setY(int)` when called on an | |||
instance of `Point`. Here's another example: | |||
[source, java] | |||
.... | |||
pointcut ioHandler(): within(MyClass) && handler(IOException); | |||
.... | |||
@@ -230,7 +238,7 @@ when the target object is of type `SomeType`:: | |||
`target(SomeType)` | |||
when the executing code belongs to class `MyClass`:: | |||
`within(MyClass)` | |||
when the join point is in the control flow of a call to a `Test`'s | |||
when the join point is in the control flow of a call to a ``Test``'s | |||
no-argument `main` method:: | |||
`cflow(call(void Test.main()))` | |||
@@ -256,9 +264,9 @@ such `set` method; this pointcut picks out calls to all of them. | |||
means (1) the execution of any method with no parameters that returns an | |||
`int`, (2) the call to any `setY` method that takes a `long` as an | |||
argument, regardless of return type or declaring type, (3) the call to | |||
any of `Point`'s `setY` methods that take an `int` as an argument, | |||
any of ``Point``'s `setY` methods that take an `int` as an argument, | |||
regardless of return type, and (4) the call to any classes' constructor, | |||
so long as it takes exactly two `int`s as arguments. | |||
so long as it takes exactly two ``int``s as arguments. | |||
* You can compose pointcuts. For example, | |||
[arabic] | |||
. `target(Point) && call(int *())` | |||
@@ -270,7 +278,7 @@ so long as it takes exactly two `int`s as arguments. | |||
+ | |||
means (1) any call to an `int` method with no arguments on an instance | |||
of `Point`, regardless of its name, (2) any call to any method where the | |||
call is made from the code in `Point`'s or `Line`'s type declaration, | |||
call is made from the code in ``Point``'s or ``Line``'s type declaration, | |||
(3) the execution of any constructor taking exactly one `int` argument, | |||
regardless of where the call is made from, and (4) any method call to an | |||
`int` method when the executing object is any type except `Point`. | |||
@@ -286,12 +294,13 @@ non-static method, and (3) any execution of a public, non-static method. | |||
* Pointcuts can also deal with interfaces. For example, given the | |||
interface | |||
+ | |||
[source, java] | |||
.... | |||
interface MyInterface { ... } | |||
.... | |||
+ | |||
the pointcut `call(* MyInterface.*(..))` picks out any call to a method | |||
in `MyInterface`'s signature -- that is, any method defined by | |||
in ``MyInterface``'s signature -- that is, any method defined by | |||
`MyInterface` or inherited by one of its a supertypes. | |||
[[call-vs-execution]] | |||
@@ -339,6 +348,7 @@ primitive pointcuts like `cflow` and `cflowbelow`. Here's an example: | |||
`cflow(P)` picks out each join point in the control flow of the join | |||
points picked out by <P>. So, pictorially: | |||
[source, text] | |||
.... | |||
P --------------------- | |||
\ | |||
@@ -350,6 +360,7 @@ What does `cflow(P) && | |||
cflow(Q)` pick out? Well, it picks out each join point that is | |||
in both the control flow of <P> and in the control flow of <Q>. So... | |||
[source, text] | |||
.... | |||
P --------------------- | |||
\ | |||
@@ -370,6 +381,7 @@ But what does `cflow(P | |||
&& Q)` mean? Well, it means the control flow of those join | |||
points that are both picked out by <P> and picked out by <Q>. | |||
[source, text] | |||
.... | |||
P && Q ------------------- | |||
\ | |||
@@ -384,6 +396,7 @@ control flow of `(P && | |||
Here's some code that expresses this. | |||
[source, java] | |||
.... | |||
public class Test { | |||
public static void main(String[] args) { | |||
@@ -422,6 +435,7 @@ for more details.) | |||
Consider again the first pointcut definition in this chapter: | |||
[source, java] | |||
.... | |||
pointcut setter(): target(Point) && | |||
(call(void setX(int)) || | |||
@@ -435,6 +449,7 @@ side. An empty parameter list means that none of the context from the | |||
join points is published from this pointcut. But consider another | |||
version of version of this pointcut definition: | |||
[source, java] | |||
.... | |||
pointcut setter(Point p): target(p) && | |||
(call(void setX(int)) || | |||
@@ -452,6 +467,7 @@ matched join point. | |||
Here's another example that illustrates the flexible mechanism for | |||
defining pointcut parameters: | |||
[source, java] | |||
.... | |||
pointcut testEquality(Point p): target(Point) && | |||
args(p) && | |||
@@ -464,10 +480,11 @@ access to a `Point` from each join point. But in this case, looking at | |||
the right-hand side we find that the object named in the parameters is | |||
not the target `Point` object that receives the call; it's the argument | |||
(also of type `Point`) passed to the `equals` method when some other | |||
`Point` is the target. If we wanted access to both `Point`s, then the | |||
`Point` is the target. If we wanted access to both ``Point``s, then the | |||
pointcut definition that would expose target `Point p1` and argument | |||
`Point p2` would be | |||
[source, java] | |||
.... | |||
pointcut testEquality(Point p1, Point p2): target(p1) && | |||
args(p2) && | |||
@@ -476,6 +493,7 @@ pointcut testEquality(Point p1, Point p2): target(p1) && | |||
Let's look at another variation of the `setters` pointcut: | |||
[source, java] | |||
.... | |||
pointcut setter(Point p, int newval): target(p) && | |||
args(newval) && | |||
@@ -493,6 +511,7 @@ important rule is that all the pointcut parameters must be bound at | |||
every join point picked out by the pointcut. So, for example, the | |||
following pointcut definition will result in a compilation error: | |||
[source, java] | |||
.... | |||
pointcut badPointcut(Point p1, Point p2): | |||
(target(p1) && call(void setX(int))) || | |||
@@ -512,6 +531,7 @@ operations to their `Partner` objects. The aspect `HandleLiveness` | |||
ensures that, before the delegations, the partner exists and is alive, | |||
or else it throws an exception. | |||
[source, java] | |||
.... | |||
class Handle { | |||
Partner partner = new Partner(); | |||
@@ -594,6 +614,7 @@ given either by named pointcuts (like the ones you've seen above) or by | |||
anonymous pointcuts. Here is an example of an advice on a named | |||
pointcut: | |||
[source, java] | |||
.... | |||
pointcut setter(Point p1, int newval): target(p1) && args(newval) | |||
(call(void setX(int) || | |||
@@ -607,6 +628,7 @@ before(Point p1, int newval): setter(p1, newval) { | |||
And here is exactly the same example, but using an anonymous pointcut: | |||
[source, java] | |||
.... | |||
before(Point p1, int newval): target(p1) && args(newval) | |||
(call(void setX(int)) || | |||
@@ -621,6 +643,7 @@ Here are examples of the different advice: | |||
This before advice runs just before the join points picked out by the | |||
(anonymous) pointcut: | |||
[source, java] | |||
.... | |||
before(Point p, int x): target(p) && args(x) && call(void setX(int)) { | |||
if (!p.assertX(x)) return; | |||
@@ -631,6 +654,7 @@ This after advice runs just after each join point picked out by the | |||
(anonymous) pointcut, regardless of whether it returns normally or | |||
throws an exception: | |||
[source, java] | |||
.... | |||
after(Point p, int x): target(p) && args(x) && call(void setX(int)) { | |||
if (!p.assertX(x)) throw new PostConditionViolation(); | |||
@@ -642,6 +666,7 @@ by the (anonymous) pointcut, but only if it returns normally. The return | |||
value can be accessed, and is named `x` here. After the advice runs, the | |||
return value is returned: | |||
[source, java] | |||
.... | |||
after(Point p) returning(int x): target(p) && call(int getX()) { | |||
System.out.println("Returning int value " + x + " for p = " + p); | |||
@@ -653,6 +678,7 @@ the (anonymous) pointcut, but only when it throws an exception of type | |||
`Exception`. Here the exception value can be accessed with the name `e`. | |||
The advice re-raises the exception after it's done: | |||
[source, java] | |||
.... | |||
after() throwing(Exception e): target(Point) && call(void setX(int)) { | |||
System.out.println(e); | |||
@@ -663,6 +689,7 @@ This around advice traps the execution of the join point; it runs | |||
_instead_ of the join point. The original action associated with the | |||
join point can be invoked through the special `proceed` call: | |||
[source, java] | |||
.... | |||
void around(Point p, int x): target(p) | |||
&& args(x) | |||
@@ -683,6 +710,7 @@ class. Here are examples of some such inter-type declarations: | |||
This declares that each `Server` has a `boolean` field named `disabled`, | |||
initialized to `false`: | |||
[source, java] | |||
.... | |||
private boolean Server.disabled = false; | |||
.... | |||
@@ -696,6 +724,7 @@ another aspect) there won't be a name collision, since no reference to | |||
This declares that each `Point` has an `int` method named `getX` with no | |||
arguments that returns whatever `this.x` is: | |||
[source, java] | |||
.... | |||
public int Point.getX() { return this.x; } | |||
.... | |||
@@ -707,6 +736,7 @@ conflict. | |||
This publically declares a two-argument constructor for `Point`: | |||
[source, java] | |||
.... | |||
public Point.new(int x, int y) { this.x = x; this.y = y; } | |||
.... | |||
@@ -714,6 +744,7 @@ public Point.new(int x, int y) { this.x = x; this.y = y; } | |||
This publicly declares that each `Point` has an `int` field named `x`, | |||
initialized to zero: | |||
[source, java] | |||
.... | |||
public int Point.x = 0; | |||
.... | |||
@@ -724,6 +755,7 @@ has a field named `x` (defined by `Point` or by another aspect). | |||
This declares that the `Point` class implements the `Comparable` | |||
interface: | |||
[source, java] | |||
.... | |||
declare parents: Point implements Comparable; | |||
.... | |||
@@ -734,6 +766,7 @@ required by `Comparable`. | |||
This declares that the `Point` class extends the `GeometricObject` | |||
class. | |||
[source, java] | |||
.... | |||
declare parents: Point extends GeometricObject; | |||
.... | |||
@@ -741,6 +774,7 @@ declare parents: Point extends GeometricObject; | |||
An aspect can have several inter-type declarations. For example, the | |||
following declarations | |||
[source, java] | |||
.... | |||
public String Point.name; | |||
public void Point.setName(String name) { this.name = name; } | |||
@@ -754,6 +788,7 @@ An inter-type member can only have one target type, but often you may | |||
wish to declare the same member on more than one type. This can be done | |||
by using an inter-type member in combination with a private interface: | |||
[source, java] | |||
.... | |||
aspect A { | |||
private interface HasName {} | |||
@@ -782,18 +817,20 @@ declarations in addition to public inter-type declarations. Private | |||
means private in relation to the aspect, not necessarily the target | |||
type. So, if an aspect makes a private inter-type declaration of a field | |||
[source, java] | |||
.... | |||
private int Foo.x; | |||
.... | |||
Then code in the aspect can refer to `Foo`'s `x` field, but nobody else | |||
Then code in the aspect can refer to ``Foo``'s `x` field, but nobody else | |||
can. Similarly, if an aspect makes a package-protected introduction, | |||
[source, java] | |||
.... | |||
int Foo.x; | |||
int Foo.x; | |||
.... | |||
then everything in the aspect's package (which may or may not be `Foo`'s | |||
then everything in the aspect's package (which may or may not be ``Foo``'s | |||
package) can access `x`. | |||
==== Example: `PointAssertions` | |||
@@ -806,6 +843,7 @@ other parts of the program (including the code in `Point`) have no | |||
business accessing the assert methods. Only the code inside of the | |||
aspect can call those methods. | |||
[source, java] | |||
.... | |||
class Point { | |||
int x, y; | |||
@@ -856,6 +894,7 @@ One way to use it is simply to print it out. Like all Java objects, | |||
`thisJoinPoint` has a `toString()` method that makes quick-and-dirty | |||
tracing easy: | |||
[source, java] | |||
.... | |||
aspect TraceNonStaticMethods { | |||
before(Point p): target(p) && call(* *(..)) { | |||
@@ -868,6 +907,7 @@ The type of `thisJoinPoint` includes a rich reflective class hierarchy | |||
of signatures, and can be used to access both static and dynamic | |||
information about join points such as the arguments of the join point: | |||
[source, java] | |||
.... | |||
thisJoinPoint.getArgs() | |||
.... | |||
@@ -876,6 +916,7 @@ In addition, it holds an object consisting of all the static information | |||
about the join point such as corresponding line number and static | |||
signature: | |||
[source, java] | |||
.... | |||
thisJoinPoint.getStaticPart() | |||
.... | |||
@@ -888,6 +929,7 @@ necessary when using `thisJoinPoint` directly. | |||
It is always the case that | |||
[source, java] | |||
.... | |||
thisJoinPointStaticPart == thisJoinPoint.getStaticPart() | |||
@@ -903,8 +945,9 @@ but it is not the current but the enclosing join point. So, for example, | |||
it is possible to print out the calling source location (if available) | |||
with | |||
[source, java] | |||
.... | |||
before() : execution (* *(..)) { | |||
System.err.println(thisEnclosingJoinPointStaticPart.getSourceLocation()) | |||
} | |||
before() : execution (* *(..)) { | |||
System.err.println(thisEnclosingJoinPointStaticPart.getSourceLocation()) | |||
} | |||
.... |
@@ -11,6 +11,7 @@ surprising behavior and how to understand them. | |||
Here is a Java program with peculiar behavior | |||
[source, java] | |||
.... | |||
public class Main { | |||
public static void main(String[] args) { | |||
@@ -39,6 +40,7 @@ the completely silent abort. | |||
The following short aspect will also generate this behavior: | |||
[source, java] | |||
.... | |||
aspect A { | |||
before(): call(* *(..)) { System.out.println("before"); } | |||
@@ -50,6 +52,7 @@ Why? Because the call to println is also a call matched by the pointcut | |||
`call (* *(..))`. We get no output because we used simple after() | |||
advice. If the aspect were changed to | |||
[source, java] | |||
.... | |||
aspect A { | |||
before(): call(* *(..)) { System.out.println("before"); } | |||
@@ -65,6 +68,7 @@ There's a simple idiom to use if you ever have a worry that your advice | |||
might apply in this way. Just restrict the advice from occurring in join | |||
points caused within the aspect. So: | |||
[source, java] | |||
.... | |||
aspect A { | |||
before(): call(* *(..)) && !within(A) { System.out.println("before"); } | |||
@@ -75,6 +79,7 @@ aspect A { | |||
Other solutions might be to more closely restrict the pointcut in other | |||
ways, for example: | |||
[source, java] | |||
.... | |||
aspect A { | |||
before(): call(* MyObject.*(..)) { System.out.println("before"); } |
@@ -9,16 +9,16 @@ | |||
|*Methods and Constructors* | | |||
|`call(Signature)` |every call to any method or constructor matching | |||
<Signature> at the call site | |||
`<Signature>` at the call site | |||
|`execution(Signature)` |every execution of any method or constructor | |||
matching <Signature> | |||
matching `<Signature>` | |||
|*Fields* | | |||
|`get(Signature)` |every reference to any field matching <Signature> | |||
|`get(Signature)` |every reference to any field matching `<Signature>` | |||
|`set(Signature)` |every assignment to any field matching <Signature>. | |||
|`set(Signature)` |every assignment to any field matching `<Signature>`. | |||
The assigned value can be exposed with an `args` pointcut | |||
|*Exception Handlers* | | |||
@@ -37,12 +37,12 @@ pointcut | |||
initializer for any type in <TypePattern> | |||
|`initialization(Signature)` |every initialization of an object when the | |||
first constructor called in the type matches <Signature>, encompassing | |||
first constructor called in the type matches `<Signature>`, encompassing | |||
the return from the super constructor call to the return of the | |||
first-called constructor | |||
|`preinitialization(Signature)` |every pre-initialization of an object | |||
when the first constructor called in the type matches <Signature>, | |||
when the first constructor called in the type matches `<Signature>`, | |||
encompassing the entry of the first-called constructor to the call to | |||
the super constructor | |||
@@ -52,7 +52,7 @@ the super constructor | |||
<TypePattern> | |||
|`withincode(Signature)` |every join point from code defined in a method | |||
or constructor matching <Signature> | |||
or constructor matching `<Signature>` | |||
|=== | |||
[[quick-typePatterns]] | |||
@@ -62,290 +62,118 @@ A type pattern is one of | |||
[cols=",",] | |||
|=== | |||
|<TypeNamePattern> |all types in <TypeNamePattern> | |||
|*Type pattern* | | |||
|<SubtypePattern> |all types in <SubtypePattern>, a pattern with a +. | |||
|`<TypeNamePattern>` |all types in `<TypeNamePattern>` | |||
|<ArrayTypePattern> |all types in <ArrayTypePattern>, a pattern with one | |||
or more []s. | |||
|`<SubtypePattern>` |all types in `<SubtypePattern>`, a pattern with a `+` | |||
|`<ArrayTypePattern>` |all types in `<ArrayTypePattern>`, a pattern with one or more ``[]``s. | |||
|`!TypePattern` |all types not in <TypePattern> | |||
|`TypePattern0 | |||
&& TypePattern1` |all types in both <TypePattern0> and | |||
<TypePattern1> | |||
|`TypePattern0 && TypePattern1` |all types in both `<TypePattern0>` and `<TypePattern1>` | |||
|`TypePattern0 || TypePattern1` |all types in either <TypePattern0> or | |||
<TypePattern1> | |||
|`TypePattern0 \|\| TypePattern1` |all types in either `<TypePattern0>` or `<TypePattern1>` | |||
|`( TypePattern )` |all types in <TypePattern> | |||
|`( TypePattern )` |all types in `<TypePattern>` | |||
|=== | |||
where <TypeNamePattern> can either be a plain type name, the wildcard | |||
`*` (indicating all types), or an identifier with embedded `*` and `..` | |||
where `<TypeNamePattern>` can either be a plain type name, the wildcard | |||
`\*` (indicating all types), or an identifier with embedded `*` and `..` | |||
wildcards. | |||
An embedded `*` in an identifier matches any sequence of characters, but | |||
does not match the package (or inner-type) separator ".". | |||
does not match the package (or inner-type) separator `.`. | |||
An embedded `..` in an identifier matches any sequence of characters | |||
that starts and ends with the package (or inner-type) separator ".". | |||
that starts and ends with the package (or inner-type) separator `.`. | |||
[[quick-advice]] | |||
=== Advice | |||
Each piece of advice is of the form | |||
____ | |||
[ strictfp ] | |||
AdviceSpec | |||
[ throws | |||
TypeList | |||
] : | |||
Pointcut | |||
[source, text] | |||
.... | |||
[ strictfp ] AdviceSpec [ throws TypeList ] : Pointcut { Body } | |||
.... | |||
\{ | |||
where `<AdviceSpec>` is one of | |||
Body | |||
} | |||
____ | |||
where <AdviceSpec> is one of | |||
`before( Formals ) `:: | |||
`before( Formals )`:: | |||
runs before each join point | |||
`after( Formals ) returning | |||
[ ( Formal ) ] `:: | |||
`after( Formals ) returning [ ( Formal ) ]`:: | |||
runs after each join point that returns normally. The optional formal | |||
gives access to the returned value | |||
`after( Formals ) throwing [ | |||
( Formal ) ] `:: | |||
runs after each join point that throws a | |||
+ | |||
Throwable | |||
+ | |||
. If the optional formal is present, runs only after each join point | |||
that throws a | |||
+ | |||
Throwable | |||
+ | |||
of the type of | |||
+ | |||
Formal | |||
+ | |||
, and | |||
+ | |||
Formal | |||
+ | |||
gives access to the | |||
+ | |||
Throwable | |||
+ | |||
exception value | |||
`after( Formals ) `:: | |||
`after( Formals ) throwing [ ( Formal ) ]`:: | |||
runs after each join point that throws a `Throwable`. | |||
If the optional formal is present, runs only after each join point | |||
that throws a `Throwable` of the type of `Formal`, and `Formal` gives access to the | |||
`Throwable` exception value | |||
`after( Formals )`:: | |||
runs after each join point regardless of whether it returns normally | |||
or throws a | |||
+ | |||
Throwable | |||
`Type | |||
around( Formals ) `:: | |||
or throws a `Throwable` | |||
`Type around( Formals )`:: | |||
runs in place of each join point. The join point can be executed by | |||
calling | |||
+ | |||
proceed | |||
+ | |||
, which takes the same number and types of arguments as the around | |||
calling `proceed`, which takes the same number and types of arguments as the around | |||
advice. | |||
Three special variables are available inside of advice bodies: | |||
`thisJoinPoint`:: | |||
an object of type | |||
+ | |||
org.aspectj.lang.JoinPoint | |||
+ | |||
representing the join point at which the advice is executing. | |||
an object of type `org.aspectj.lang.JoinPoint` representing the join point | |||
at which the advice is executing | |||
`thisJoinPointStaticPart`:: | |||
equivalent to | |||
+ | |||
thisJoinPoint.getStaticPart() | |||
+ | |||
, but may use fewer runtime resources. | |||
equivalent to `thisJoinPoint.getStaticPart()`, but may use fewer runtime resources | |||
`thisEnclosingJoinPointStaticPart`:: | |||
the static part of the dynamically enclosing join point. | |||
the static part of the dynamically enclosing join point | |||
[[quick-interType]] | |||
=== Inter-type member declarations | |||
Each inter-type member is one of | |||
` | |||
Modifiers ReturnType OnType . Id | |||
( Formals ) | |||
[ throws TypeList ] | |||
{ Body } | |||
`:: | |||
a method on | |||
+ | |||
OnType | |||
+ | |||
. | |||
` | |||
abstract Modifiers ReturnType OnType . Id | |||
( Formals ) | |||
[ throws TypeList ] ; | |||
`:: | |||
an abstract method on | |||
+ | |||
OnType | |||
+ | |||
. | |||
` | |||
Modifiers OnType . new | |||
( Formals ) | |||
[ throws TypeList ] | |||
{ Body } | |||
`:: | |||
a constructor on | |||
+ | |||
OnType | |||
+ | |||
. | |||
` | |||
Modifiers Type OnType . Id | |||
[ = Expression ] ; | |||
`:: | |||
a field on | |||
+ | |||
OnType | |||
+ | |||
. | |||
`Modifiers ReturnType OnType . Id ( Formals ) [ throws TypeList ] { Body }`:: | |||
a method on `OnType` | |||
`abstract Modifiers ReturnType OnType . Id ( Formals ) [ throws TypeList ] ;`:: | |||
an abstract method on `OnType` | |||
`Modifiers OnType . new ( Formals ) [ throws TypeList ] { Body }`:: | |||
a constructor on `OnType` | |||
`Modifiers Type OnType . Id [ = Expression ] ;`:: | |||
a field on `OnType` | |||
[[quick-other]] | |||
=== Other declarations | |||
` | |||
declare parents : | |||
TypePattern extends | |||
Type ; | |||
`:: | |||
the types in | |||
+ | |||
TypePattern | |||
+ | |||
extend | |||
+ | |||
Type | |||
+ | |||
. | |||
` | |||
declare parents : TypePattern | |||
implements TypeList ; | |||
`:: | |||
the types in | |||
+ | |||
TypePattern | |||
+ | |||
implement the types in | |||
+ | |||
TypeList | |||
+ | |||
. | |||
` | |||
declare warning : Pointcut : | |||
String ; | |||
`:: | |||
if any of the join points in | |||
+ | |||
Pointcut | |||
+ | |||
possibly exist in the program, the compiler emits the warning | |||
+ | |||
String | |||
+ | |||
. | |||
` | |||
declare error : Pointcut : | |||
String ; | |||
`:: | |||
if any of the join points in | |||
+ | |||
Pointcut | |||
+ | |||
could possibly exist in the program, the compiler emits the error | |||
+ | |||
String | |||
+ | |||
. | |||
` | |||
declare soft : | |||
Type : | |||
Pointcut ; | |||
`:: | |||
any | |||
+ | |||
Type | |||
+ | |||
exception that gets thrown at any join point picked out by | |||
+ | |||
Pointcut | |||
+ | |||
is wrapped in | |||
+ | |||
org.aspectj.lang.SoftException | |||
+ | |||
. | |||
` | |||
declare precedence : | |||
TypePatternList ; | |||
`:: | |||
`declare parents : TypePattern extends Type ;`:: | |||
the types in `TypePattern` extend `Type` | |||
`declare parents : TypePattern implements TypeList ;`:: | |||
the types in `TypePattern` implement the types in `TypeList` | |||
`declare warning : Pointcut : String ;`:: | |||
if any of the join points in `Pointcut` possibly exist in the program, | |||
the compiler emits the warning `String` | |||
`declare error : Pointcut : String ;`:: | |||
if any of the join points in `Pointcut` could possibly exist in the program, | |||
the compiler emits the error `String` | |||
`declare soft : Type : Pointcut ;`:: | |||
any `Type` exception that gets thrown at any join point picked out by `Pointcut` | |||
is wrapped in `org.aspectj.lang.SoftException` | |||
`declare precedence : TypePatternList ;`:: | |||
at any join point where multiple pieces of advice apply, the advice | |||
precedence at that join point is in | |||
+ | |||
TypePatternList | |||
+ | |||
order. | |||
precedence at that join point is in `TypePatternList` order | |||
[[quick-aspectAssociations]] | |||
=== Aspects | |||
Each aspect is of the form | |||
____ | |||
[ privileged ] | |||
Modifiers | |||
aspect | |||
Id | |||
[ extends | |||
Type | |||
] [ implements | |||
TypeList | |||
] [ | |||
PerClause | |||
] \{ | |||
Body | |||
} | |||
____ | |||
[source, text] | |||
.... | |||
[ privileged ] Modifiers aspect Id [ extends Type ] [ implements TypeList ] [ PerClause ] { Body } | |||
.... | |||
where <PerClause> defines how the aspect is instantiated and associated | |||
where `<PerClause>` defines how the aspect is instantiated and associated | |||
(`issingleton()` by default): | |||
[cols=",,",options="header",] | |||
@@ -355,18 +183,18 @@ where <PerClause> defines how the aspect is instantiated and associated | |||
default. |`aspectOf()` at all join points | |||
|`perthis(Pointcut)` |An instance is associated with each object that is | |||
the currently executing object at any join point in <Pointcut>. | |||
the currently executing object at any join point in `<Pointcut>`. | |||
|`aspectOf(Object)` at all join points | |||
|`pertarget(Pointcut)` |An instance is associated with each object that | |||
is the target object at any join point in <Pointcut>. | |||
is the target object at any join point in `<Pointcut>`. | |||
|`aspectOf(Object)` at all join points | |||
|`percflow(Pointcut)` |The aspect is defined for each entrance to the | |||
control flow of the join points defined by <Pointcut>. |`aspectOf()` at | |||
control flow of the join points defined by `<Pointcut>`. |`aspectOf()` at | |||
join points in `cflow(Pointcut)` | |||
|`percflowbelow(Pointcut)` |The aspect is defined for each entrance to | |||
the control flow below the join points defined by <Pointcut>. | |||
the control flow below the join points defined by `<Pointcut>`. | |||
|`aspectOf()` at join points in `cflowbelow(Pointcut)` | |||
|=== |
@@ -63,11 +63,7 @@ Constructor call:: | |||
Constructor execution:: | |||
When the body of code for an actual constructor executes, after its | |||
this or super constructor call. The object being constructed is the | |||
currently executing object, and so may be accessed with the | |||
+ | |||
this | |||
+ | |||
pointcut. The constructor execution join point for a constructor that | |||
currently executing object, and so may be accessed with the `_this_` pointcut. The constructor execution join point for a constructor that | |||
calls a super constructor also includes any non-static initializers of | |||
enclosing class. No value is returned from a constructor execution | |||
join point, so its return type is considered to be void. | |||
@@ -80,15 +76,7 @@ Object pre-initialization:: | |||
This encompasses the time between the start of its first called | |||
constructor and the start of its parent's constructor. Thus, the | |||
execution of these join points encompass the join points of the | |||
evaluation of the arguments of | |||
+ | |||
this() | |||
+ | |||
and | |||
+ | |||
super() | |||
+ | |||
constructor calls. No value is returned from an object | |||
evaluation of the arguments of `_this()_` and `_super()_` constructor calls. No value is returned from an object | |||
pre-initialization join point, so its return type is considered to be | |||
void. | |||
Object initialization:: | |||
@@ -97,11 +85,7 @@ Object initialization:: | |||
and the return of its first called constructor. It includes all the | |||
dynamic initializers and constructors used to create the object. The | |||
object being constructed is the currently executing object, and so may | |||
be accessed with the | |||
+ | |||
this | |||
+ | |||
pointcut. No value is returned from a constructor execution join | |||
be accessed with the `_this_` pointcut. No value is returned from a constructor execution join | |||
point, so its return type is considered to be void. | |||
Field reference:: | |||
When a non-constant field is referenced. [Note that references to | |||
@@ -180,219 +164,84 @@ build up other pointcuts. The primitive pointcuts and combinators | |||
provided by the language are: | |||
`call(MethodPattern)`:: | |||
Picks out each method call join point whose signature matches | |||
+ | |||
MethodPattern | |||
+ | |||
. | |||
Picks out each method call join point whose signature matches `_MethodPattern_`. | |||
`execution(MethodPattern)`:: | |||
Picks out each method execution join point whose signature matches | |||
+ | |||
MethodPattern | |||
+ | |||
. | |||
Picks out each method execution join point whose signature matches `_MethodPattern_`. | |||
`get(FieldPattern)`:: | |||
Picks out each field reference join point whose signature matches | |||
+ | |||
FieldPattern | |||
+ | |||
. [Note that references to constant fields (static final fields bound | |||
Picks out each field reference join point whose signature matches `_FieldPattern_`. [Note that references to constant fields (static final fields bound | |||
to a constant string object or primitive value) are not join points, | |||
since Java requires them to be inlined.] | |||
`set(FieldPattern)`:: | |||
Picks out each field set join point whose signature matches | |||
+ | |||
FieldPattern | |||
+ | |||
. [Note that the initializations of constant fields (static final | |||
Picks out each field set join point whose signature matches `_FieldPattern_`. [Note that the initializations of constant fields (static final | |||
fields where the initializer is a constant string object or primitive | |||
value) are not join points, since Java requires their references to be | |||
inlined.] | |||
`call(ConstructorPattern)`:: | |||
Picks out each constructor call join point whose signature matches | |||
+ | |||
ConstructorPattern | |||
+ | |||
. | |||
Picks out each constructor call join point whose signature matches `_ConstructorPattern_`. | |||
`execution(ConstructorPattern)`:: | |||
Picks out each constructor execution join point whose signature | |||
matches | |||
+ | |||
ConstructorPattern | |||
+ | |||
. | |||
matches `_ConstructorPattern_`. | |||
`initialization(ConstructorPattern)`:: | |||
Picks out each object initialization join point whose signature | |||
matches | |||
+ | |||
ConstructorPattern | |||
+ | |||
. | |||
matches `_ConstructorPattern_`. | |||
`preinitialization(ConstructorPattern)`:: | |||
Picks out each object pre-initialization join point whose signature | |||
matches | |||
+ | |||
ConstructorPattern | |||
+ | |||
. | |||
matches `_ConstructorPattern_`. | |||
`staticinitialization(TypePattern)`:: | |||
Picks out each static initializer execution join point whose signature | |||
matches | |||
+ | |||
TypePattern | |||
+ | |||
. | |||
matches `_TypePattern_`. | |||
`handler(TypePattern)`:: | |||
Picks out each exception handler join point whose signature matches | |||
+ | |||
TypePattern | |||
+ | |||
. | |||
Picks out each exception handler join point whose signature matches `_TypePattern_`. | |||
`adviceexecution()`:: | |||
Picks out all advice execution join points. | |||
`within(TypePattern)`:: | |||
Picks out each join point where the executing code is defined in a | |||
type matched by | |||
+ | |||
TypePattern | |||
+ | |||
. | |||
type matched by `_TypePattern_`. | |||
`withincode(MethodPattern)`:: | |||
Picks out each join point where the executing code is defined in a | |||
method whose signature matches | |||
+ | |||
MethodPattern | |||
+ | |||
. | |||
method whose signature matches `_MethodPattern_`. | |||
`withincode(ConstructorPattern)`:: | |||
Picks out each join point where the executing code is defined in a | |||
constructor whose signature matches | |||
+ | |||
ConstructorPattern | |||
+ | |||
. | |||
constructor whose signature matches `_ConstructorPattern_`. | |||
`cflow(Pointcut)`:: | |||
Picks out each join point in the control flow of any join point | |||
+ | |||
P | |||
+ | |||
picked out by | |||
+ | |||
Pointcut | |||
+ | |||
, including | |||
+ | |||
P | |||
+ | |||
itself. | |||
Picks out each join point in the control flow of any join point `_P_` picked out by `_Pointcut_` , including `_P_` itself. | |||
`cflowbelow(Pointcut)`:: | |||
Picks out each join point in the control flow of any join point | |||
+ | |||
P | |||
+ | |||
picked out by | |||
+ | |||
Pointcut | |||
+ | |||
, but not | |||
+ | |||
P | |||
+ | |||
itself. | |||
Picks out each join point in the control flow of any join point `_P_` picked out by `_Pointcut_`, but not `_P_` itself. | |||
`this(Type or Id)`:: | |||
Picks out each join point where the currently executing object (the | |||
object bound to | |||
+ | |||
this | |||
+ | |||
) is an instance of | |||
+ | |||
Type | |||
+ | |||
, or of the type of the identifier | |||
+ | |||
Id | |||
+ | |||
(which must be bound in the enclosing advice or pointcut definition). | |||
object bound to `_this_`) is an instance of `_Type_` , or of the type of the identifier `_Id_` (which must be bound in the enclosing advice or pointcut definition). | |||
Will not match any join points from static contexts. | |||
`target(Type or Id)`:: | |||
Picks out each join point where the target object (the object on which | |||
a call or field operation is applied to) is an instance of | |||
+ | |||
Type | |||
+ | |||
, or of the type of the identifier | |||
+ | |||
Id | |||
+ | |||
(which must be bound in the enclosing advice or pointcut definition). | |||
a call or field operation is applied to) is an instance of `_Type_` , or of the type of the identifier `_Id_` (which must be bound in the enclosing advice or pointcut definition). | |||
Will not match any calls, gets, or sets of static members. | |||
`args(Type or Id, ...)`:: | |||
Picks out each join point where the arguments are instances of the | |||
appropriate type (or type of the identifier if using that form). A | |||
+ | |||
null | |||
+ | |||
argument is matched iff the static type of the argument (declared | |||
appropriate type (or type of the identifier if using that form). A `_null_` argument is matched iff the static type of the argument (declared | |||
parameter type or field type) is the same as, or a subtype of, the | |||
specified args type. | |||
`PointcutId(TypePattern or Id, ...)`:: | |||
Picks out each join point that is picked out by the user-defined | |||
pointcut designator named by | |||
+ | |||
PointcutId | |||
+ | |||
. | |||
pointcut designator named by `_PointcutId_` . | |||
`if(BooleanExpression)`:: | |||
Picks out each join point where the boolean expression evaluates to | |||
+ | |||
true | |||
+ | |||
. The boolean expression used can only access static members, | |||
parameters exposed by the enclosing pointcut or advice, and | |||
+ | |||
thisJoinPoint | |||
+ | |||
forms. In particular, it cannot call non-static methods on the aspect | |||
Picks out each join point where the boolean expression evaluates to `_true_` . The boolean expression used can only access static members, | |||
parameters exposed by the enclosing pointcut or advice, and `_thisJoinPoint_` forms. In particular, it cannot call non-static methods on the aspect | |||
or use return values or exceptions exposed by after advice. | |||
`! Pointcut`:: | |||
Picks out each join point that is not picked out by | |||
+ | |||
Pointcut | |||
+ | |||
. | |||
Picks out each join point that is not picked out by `_Pointcut_` . | |||
`Pointcut0 && Pointcut1`:: | |||
Picks out each join points that is picked out by both | |||
+ | |||
Pointcut0 | |||
+ | |||
and | |||
+ | |||
Pointcut1 | |||
+ | |||
. | |||
Picks out each join points that is picked out by both `_Pointcut0_` and `_Pointcut1_` . | |||
`Pointcut0 || Pointcut1`:: | |||
Picks out each join point that is picked out by either pointcuts. | |||
+ | |||
Pointcut0 | |||
+ | |||
or | |||
+ | |||
Pointcut1 | |||
+ | |||
. | |||
Picks out each join point that is picked out by either pointcuts. `_Pointcut0_` or `_Pointcut1_` . | |||
`( Pointcut )`:: | |||
Picks out each join points picked out by | |||
+ | |||
Pointcut | |||
+ | |||
. | |||
Picks out each join points picked out by `_Pointcut_` . | |||
==== Pointcut definition | |||
Pointcuts are defined and named by the programmer with the `pointcut` | |||
declaration. | |||
[source, java] | |||
.... | |||
pointcut publicIntCall(int i): | |||
call(public * *(int)) && args(i); | |||
@@ -402,6 +251,7 @@ A named pointcut may be defined in either a class or aspect, and is | |||
treated as a member of the class or aspect where it is found. As a | |||
member, it may have an access modifier such as `public` or `private`. | |||
[source, java] | |||
.... | |||
class C { | |||
pointcut publicCall(int i): | |||
@@ -418,6 +268,7 @@ Pointcuts that are not final may be declared abstract, and defined | |||
without a body. Abstract pointcuts may only be declared within abstract | |||
aspects. | |||
[source, java] | |||
.... | |||
abstract aspect A { | |||
abstract pointcut publicCall(int i); | |||
@@ -426,6 +277,7 @@ abstract aspect A { | |||
In such a case, an extending aspect may override the abstract pointcut. | |||
[source, java] | |||
.... | |||
aspect B extends A { | |||
pointcut publicCall(int i): call(public Foo.m(int)) && args(i); | |||
@@ -444,6 +296,7 @@ is different than the scope of other members; the scope of other members | |||
is the enclosing class _body_. This means that the following code is | |||
legal: | |||
[source, java] | |||
.... | |||
aspect B percflow(publicCall()) { | |||
pointcut publicCall(): call(public Foo.m(int)); | |||
@@ -466,6 +319,7 @@ collection of types. The pointcut designators that allow this are | |||
rather than a type does two things. First, it selects join points as | |||
based on the type of the formal parameter. So the pointcut | |||
[source, java] | |||
.... | |||
pointcut intArg(int i): args(i); | |||
.... | |||
@@ -477,6 +331,7 @@ advice or pointcut. | |||
Values can be exposed from named pointcuts as well, so | |||
[source, java] | |||
.... | |||
pointcut publicCall(int x): call(public *.*(int)) && intArg(x); | |||
pointcut intArg(int i): args(i); | |||
@@ -489,6 +344,7 @@ There is one special case for this kind of exposure. Exposing an | |||
argument of type Object will also match primitive typed arguments, and | |||
expose a "boxed" version of the primitive. So, | |||
[source, java] | |||
.... | |||
pointcut publicCall(): call(public *.*(..)) && args(Object); | |||
.... | |||
@@ -496,6 +352,7 @@ pointcut publicCall(): call(public *.*(..)) && args(Object); | |||
will pick out all unary methods that take, as their only argument, | |||
subtypes of Object (i.e., not primitive types like `int`), but | |||
[source, java] | |||
.... | |||
pointcut publicCall(Object o): call(public *.*(..)) && args(o); | |||
.... | |||
@@ -507,6 +364,7 @@ argument was an `int`, then the value passed to advice will be of type | |||
The "boxing" of the primitive value is based on the _original_ primitive | |||
type. So in the following program | |||
[source, java] | |||
.... | |||
public class InstanceOf { | |||
@@ -569,6 +427,7 @@ field is being set to, so at a set join point, that value can be | |||
accessed with an `args` pointcut. So an aspect guarding a static integer | |||
variable x declared in type T might be written as | |||
[source, java] | |||
.... | |||
aspect GuardedX { | |||
static final int MAX_CHANGE = 100; | |||
@@ -632,6 +491,7 @@ the exception being handled. That value can be accessed with an `args` | |||
pointcut. So an aspect used to put `FooException` objects into some | |||
normal form before they are handled could be written as | |||
[source, java] | |||
.... | |||
aspect NormalizeFooException { | |||
before(FooException e): handler(FooException) && args(e) { | |||
@@ -650,6 +510,7 @@ of advice | |||
This can be used, for example, to filter out any join point in the | |||
control flow of advice from a particular aspect. | |||
[source, java] | |||
.... | |||
aspect TraceStuff { | |||
pointcut myAdvice(): adviceexecution() && within(TraceStuff); | |||
@@ -719,6 +580,7 @@ Object). If it is the "*" wildcard, then any argument will match, and if | |||
it is the special wildcard "..", then any number of arguments will | |||
match, just like in signature patterns. So the pointcut | |||
[source, java] | |||
.... | |||
args(int, .., String) | |||
.... | |||
@@ -762,6 +624,7 @@ Anytime such state is accessed, it is accessed through the _most recent_ | |||
control flow that matched. So the "current arg" that would be printed by | |||
the following program is zero, even though it is in many control flows. | |||
[source, java] | |||
.... | |||
class Test { | |||
public static void main(String[] args) { | |||
@@ -842,6 +705,7 @@ false. Within this expression, the `thisJoinPoint` object is available. | |||
So one (extremely inefficient) way of picking out all call join points | |||
would be to use the pointcut | |||
[source, java] | |||
.... | |||
if(thisJoinPoint.getKind().equals("call")) | |||
.... | |||
@@ -922,6 +786,7 @@ while constructor declarations omit the return type and replace the | |||
method name with the class name. The start of a particular method | |||
declaration, in class `Test`, for example, might be | |||
[source, java] | |||
.... | |||
class C { | |||
public final void foo() throws ArrayOutOfBoundsException { ... } | |||
@@ -931,12 +796,14 @@ class C { | |||
In AspectJ, method signature patterns have all these, but most elements | |||
can be replaced by wildcards. So | |||
[source, java] | |||
.... | |||
call(public final void C.foo() throws ArrayOutOfBoundsException) | |||
.... | |||
picks out call join points to that method, and the pointcut | |||
[source, java] | |||
.... | |||
call(public final void *.*() throws ArrayOutOfBoundsException) | |||
.... | |||
@@ -949,12 +816,14 @@ throw `ArrayOutOfBounds` exceptions. | |||
The defining type name, if not present, defaults to *, so another way of | |||
writing that pointcut would be | |||
[source, java] | |||
.... | |||
call(public final void *() throws ArrayOutOfBoundsException) | |||
.... | |||
The wildcard `..` indicates zero or more parameters, so | |||
[source, java] | |||
.... | |||
execution(void m(..)) | |||
.... | |||
@@ -962,6 +831,7 @@ execution(void m(..)) | |||
picks out execution join points for void methods named `m`, of any | |||
number of arguments, while | |||
[source, java] | |||
.... | |||
execution(void m(.., int)) | |||
.... | |||
@@ -974,6 +844,7 @@ signature pattern should match methods without a particular modifier, | |||
such as all non-public methods, the appropriate modifier should be | |||
negated with the `!` operator. So, | |||
[source, java] | |||
.... | |||
withincode(!public void foo()) | |||
.... | |||
@@ -981,6 +852,7 @@ withincode(!public void foo()) | |||
picks out all join points associated with code in null non-public void | |||
methods named `foo`, while | |||
[source, java] | |||
.... | |||
withincode(void foo()) | |||
.... | |||
@@ -991,12 +863,14 @@ named `foo`, regardless of access modifier. | |||
Method names may contain the * wildcard, indicating any number of | |||
characters in the method name. So | |||
[source, java] | |||
.... | |||
call(int *()) | |||
.... | |||
picks out all call join points to `int` methods regardless of name, but | |||
[source, java] | |||
.... | |||
call(int get*()) | |||
.... | |||
@@ -1009,6 +883,7 @@ than using a particular class name. So the execution join points of | |||
private null constructor of a class C defined to throw an | |||
ArithmeticException can be picked out with | |||
[source, java] | |||
.... | |||
execution(private C.new() throws ArithmeticException) | |||
.... | |||
@@ -1027,6 +902,7 @@ type used to access the method. A common mistake is to specify a | |||
declaring type for the `call` pointcut that is a subtype of the | |||
originally-declaring type. For example, given the class | |||
[source, java] | |||
.... | |||
class Service implements Runnable { | |||
public void run() { ... } | |||
@@ -1035,12 +911,14 @@ class Service implements Runnable { | |||
the following pointcut | |||
[source, java] | |||
.... | |||
call(void Service.run()) | |||
.... | |||
would fail to pick out the join point for the code | |||
[source, java] | |||
.... | |||
((Runnable) new Service()).run(); | |||
.... | |||
@@ -1049,6 +927,7 @@ Specifying the originally-declaring type is correct, but would pick out | |||
any such call (here, calls to the `run()` method of any Runnable). In | |||
this situation, consider instead picking out the target type: | |||
[source, java] | |||
.... | |||
call(void run()) && target(Service) | |||
.... | |||
@@ -1058,6 +937,7 @@ method signature specifies a declaring type, the pointcut will only | |||
match methods declared in that type, or methods that override methods | |||
declared in or inherited by that type. So the pointcut | |||
[source, java] | |||
.... | |||
execution(public void Middle.*()) | |||
.... | |||
@@ -1068,6 +948,7 @@ Middle, even if those methods are overridden in a subclass of Middle. So | |||
the pointcut would pick out the method-execution join point for Sub.m() | |||
in this code: | |||
[source, java] | |||
.... | |||
class Super { | |||
protected void m() { ... } | |||
@@ -1085,6 +966,7 @@ Type patterns may 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 | |||
@@ -1190,6 +1072,7 @@ So exact type patterns match based on usual Java scope rules. | |||
There is a special type name, *, which is also a type pattern. * picks | |||
out all types, including primitive types. So | |||
[source, java] | |||
.... | |||
call(void foo(*)) | |||
.... | |||
@@ -1202,6 +1085,7 @@ patterns. The * wildcard matches zero or more characters characters | |||
except for ".", so it can be used when types have a certain naming | |||
convention. So | |||
[source, java] | |||
.... | |||
handler(java.util.*Map) | |||
.... | |||
@@ -1209,6 +1093,7 @@ handler(java.util.*Map) | |||
picks out the types java.util.Map and java.util.java.util.HashMap, among | |||
others, and | |||
[source, java] | |||
.... | |||
handler(java.util.*) | |||
.... | |||
@@ -1221,6 +1106,7 @@ The "`..`" wildcard matches any sequence of characters that start and | |||
end with a ".", so it can be used to pick out all types in any | |||
subpackage, or all inner types. So | |||
[source, java] | |||
.... | |||
within(com.xerox..*) | |||
.... | |||
@@ -1238,6 +1124,7 @@ It is possible to pick out all subtypes of a type (or a collection of | |||
types) with the "+" wildcard. The "+" wildcard follows immediately a | |||
type name pattern. So, while | |||
[source, java] | |||
.... | |||
call(Foo.new()) | |||
.... | |||
@@ -1245,6 +1132,7 @@ call(Foo.new()) | |||
picks out all constructor call join points where an instance of exactly | |||
type Foo is constructed, | |||
[source, java] | |||
.... | |||
call(Foo+.new()) | |||
.... | |||
@@ -1252,6 +1140,7 @@ call(Foo+.new()) | |||
picks out all constructor call join points where an instance of any | |||
subtype of Foo (including Foo itself) is constructed, and the unlikely | |||
[source, java] | |||
.... | |||
call(*Handler+.new()) | |||
.... | |||
@@ -1271,6 +1160,7 @@ Type patterns are built up out of type name patterns, subtype patterns, | |||
and array type patterns, and constructed with boolean operators `&&`, | |||
`||`, and `!`. So | |||
[source, java] | |||
.... | |||
staticinitialization(Foo || Bar) | |||
.... | |||
@@ -1278,6 +1168,7 @@ staticinitialization(Foo || Bar) | |||
picks out the static initializer execution join points of either Foo or | |||
Bar, and | |||
[source, java] | |||
.... | |||
call((Foo+ && ! Foo).new(..)) | |||
.... | |||
@@ -1289,6 +1180,7 @@ not Foo itself, is constructed. | |||
Here is a summary of the pattern syntax used in AspectJ: | |||
[source, text] | |||
.... | |||
MethodPattern = | |||
[ModifiersPattern] TypePattern | |||
@@ -1397,6 +1289,7 @@ interpretations of after advice: After the execution of a join point | |||
completes normally, after it throws an exception, or after it does | |||
either one. AspectJ allows after advice for any of these situations. | |||
[source, java] | |||
.... | |||
aspect A { | |||
pointcut publicCall(): call(public Object *(..)); | |||
@@ -1415,6 +1308,7 @@ aspect A { | |||
After returning advice may not care about its returned object, in which | |||
case it may be written | |||
[source, java] | |||
.... | |||
after() returning: call(public Object *(..)) { | |||
System.out.println("Returned normally"); | |||
@@ -1448,6 +1342,7 @@ must be declared with a return type, like a method. | |||
Thus, a simple use of around advice is to make a particular method | |||
constant: | |||
[source, java] | |||
.... | |||
aspect A { | |||
int around(): call(int C.foo()) { | |||
@@ -1459,6 +1354,7 @@ aspect A { | |||
Within the body of around advice, though, the computation of the | |||
original join point can be executed with the special syntax | |||
[source, java] | |||
.... | |||
proceed( ... ) | |||
.... | |||
@@ -1468,6 +1364,7 @@ pointcut, and returns whatever the around is declared to return. So the | |||
following around advice will double the second argument to `foo` | |||
whenever it is called, and then halve its result: | |||
[source, java] | |||
.... | |||
aspect A { | |||
int around(int i): call(int C.foo(Object, int)) && args(i) { | |||
@@ -1483,6 +1380,7 @@ is originally a primitive value. And when the advice returns an Object | |||
value, that value is converted back to whatever representation it was | |||
originally. So another way to write the doubling and halving advice is: | |||
[source, java] | |||
.... | |||
aspect A { | |||
Object around(int i): call(int C.foo(Object, int)) && args(i) { | |||
@@ -1500,6 +1398,7 @@ program the first call to proceed will be treated as a method call to | |||
the `ICanProceed` instance, whereas the second call to proceed is | |||
treated as the special proceed form. | |||
[source, java] | |||
.... | |||
aspect A { | |||
Object around(ICanProceed canProceed) : execution(* *(..)) && this(canProceed) { | |||
@@ -1519,6 +1418,7 @@ method parameters. In particular, assigning to any parameter affects | |||
only the value of the parameter, not the value that it came from. This | |||
means that | |||
[source, java] | |||
.... | |||
aspect A { | |||
after() returning (int i): call(int C.foo()) { | |||
@@ -1536,6 +1436,7 @@ less-precedent advice and the underlying join point by supplying | |||
different values for the variables. For example, this aspect replaces | |||
the string bound to `s` in the named pointcut `privateData`: | |||
[source, java] | |||
.... | |||
aspect A { | |||
Object around(String s): MyPointcuts.privateData(s) { | |||
@@ -1551,6 +1452,7 @@ In the following aspect, the around advice replaces the declared target | |||
`List` with an `ArrayList`. This is valid code at compile-time since the | |||
types match. | |||
[source, java] | |||
.... | |||
import java.util.*; | |||
@@ -1565,6 +1467,7 @@ But imagine a simple program where the actual target is `LinkedList`. In | |||
this case, the advice would cause a `ClassCastException` at runtime, and | |||
`peek()` is not declared in `ArrayList`. | |||
[source, java] | |||
.... | |||
public class Test { | |||
public static void main(String[] args) { | |||
@@ -1577,6 +1480,7 @@ The `ClassCastException` can occur even in situations where it appears | |||
to be unnecessary, e.g., if the program is changed to call `size()`, | |||
declared in `List`: | |||
[source, java] | |||
.... | |||
public class Test { | |||
public static void main(String[] args) { | |||
@@ -1605,6 +1509,7 @@ signalled by the compiler. | |||
For example, in the following declarations: | |||
[source, java] | |||
.... | |||
import java.io.FileNotFoundException; | |||
@@ -1626,22 +1531,14 @@ aspect A { | |||
both pieces of advice are illegal. The first because the body throws an | |||
undeclared checked exception, and the second because field get join | |||
points cannot throw `FileNotFoundException`s. | |||
points cannot throw ``FileNotFoundException``s. | |||
The exceptions that each kind of join point in AspectJ may throw are: | |||
method call and execution:: | |||
the checked exceptions declared by the target method's | |||
+ | |||
throws | |||
+ | |||
clause. | |||
the checked exceptions declared by the target method's `_throws_` clause. | |||
constructor call and execution:: | |||
the checked exceptions declared by the target constructor's | |||
+ | |||
throws | |||
+ | |||
clause. | |||
the checked exceptions declared by the target constructor's `_throws_` clause. | |||
field get and set:: | |||
no checked exceptions can be thrown from these join points. | |||
exception handler execution:: | |||
@@ -1649,11 +1546,7 @@ exception handler execution:: | |||
static initializer execution:: | |||
no checked exceptions can be thrown from these join points. | |||
pre-initialization and initialization:: | |||
any exception that is in the throws clause of | |||
+ | |||
all | |||
+ | |||
constructors of the initialized class. | |||
any exception that is in the throws clause of all constructors of the initialized class. | |||
advice execution:: | |||
any exception that is in the throws clause of the advice. | |||
@@ -1700,6 +1593,7 @@ precedence over the one that appears later. | |||
These rules can lead to circularity, such as | |||
[source, java] | |||
.... | |||
aspect A { | |||
before(): execution(void main(String[] args)) {} | |||
@@ -1747,6 +1641,7 @@ encapsulates some of the context of the advice's current or enclosing | |||
join point. These variables exist because some pointcuts may pick out | |||
very large collections of join points. For example, the pointcut | |||
[source, java] | |||
.... | |||
pointcut publicCall(): call(public * *(..)); | |||
.... | |||
@@ -1843,6 +1738,7 @@ The effect of such a declaration is to make <OnType> support the new | |||
method. Even if <OnType> is an interface. Even if the method is neither | |||
public nor abstract. So the following is legal AspectJ code: | |||
[source, java] | |||
.... | |||
interface Iface {} | |||
@@ -1979,6 +1875,7 @@ Inter-type declarations raise the possibility of conflicts among locally | |||
declared members and inter-type members. For example, assuming | |||
`otherPackage` is not the package containing the aspect `A`, the code | |||
[source, java] | |||
.... | |||
aspect A { | |||
private Registry otherPackage.onType.r; | |||
@@ -2001,6 +1898,7 @@ there is no conflict: The aspect cannot see such a field, and no code in | |||
If `onType` defines a public field "`r`", there is a conflict: The | |||
expression | |||
[source, java] | |||
.... | |||
this.r = r | |||
.... | |||
@@ -2071,6 +1969,7 @@ might define appropriate inter-type `void | |||
fulfills the `Runnable` interface. In order to implement the methods in | |||
the `Runnable` interface, the inter-type `run()` method must be public: | |||
[source, java] | |||
.... | |||
aspect A { | |||
declare parents: SomeClass implements Runnable; | |||
@@ -2091,9 +1990,10 @@ initializers. The order of super-interface instantiation is observable. | |||
We fix this order with the following properties: A supertype is | |||
initialized before a subtype, initialized code runs only once, and the | |||
initializers for a type's superclass are run before the initializers for | |||
its superinterfaces. Consider the following hierarchy where \{`Object`, | |||
`C`, `D`, `E`} are classes, \{`M`, `N`, `O`, `P`, `Q`} are interfaces. | |||
its superinterfaces. Consider the following hierarchy where {`Object`, | |||
`C`, `D`, `E`} are classes, {`M`, `N`, `O`, `P`, `Q`} are interfaces. | |||
[source, text] | |||
.... | |||
Object M O | |||
\ / \ / | |||
@@ -2106,6 +2006,7 @@ its superinterfaces. Consider the following hierarchy where \{`Object`, | |||
when a new `E` is instantiated, the initializers run in this order: | |||
[source, text] | |||
.... | |||
Object M C O N D Q P E | |||
.... | |||
@@ -2158,6 +2059,7 @@ Pointcut | |||
For example, the aspect | |||
[source, java] | |||
.... | |||
aspect A { | |||
declare soft: Exception: execution(void main(String[] args)); | |||
@@ -2169,6 +2071,7 @@ Would, at the execution join point, catch any `Exception` and rethrow a | |||
This is similar to what the following advice would do | |||
[source, java] | |||
.... | |||
aspect A { | |||
void around() execution(void main(String[] args)) { | |||
@@ -2187,6 +2090,7 @@ Like advice, the declare soft form has no effect in an abstract aspect | |||
that is not extended by a concreate aspect. So the following code will | |||
not compile unless it is compiled with an extending concrete aspect: | |||
[source, java] | |||
.... | |||
abstract aspect A { | |||
abstract pointcut softeningPC(); | |||
@@ -2223,6 +2127,7 @@ of their name should have precedence over all other aspects, and (2) the | |||
Logging aspect (and any aspect that extends it) should have precedence | |||
over all non-security aspects, can be expressed by: | |||
[source, java] | |||
.... | |||
declare precedence: *..*Security*, Logging+, *; | |||
.... | |||
@@ -2235,6 +2140,7 @@ accomplished by stating that CountEntry has precedence over | |||
DisallowNulls. This declaration could be in either aspect, or in | |||
another, ordering aspect: | |||
[source, java] | |||
.... | |||
aspect Ordering { | |||
declare precedence: CountEntry, DisallowNulls; | |||
@@ -2259,6 +2165,7 @@ aspect CountEntry { | |||
It is an error for any aspect to be matched by more than one TypePattern | |||
in a single decare precedence, so: | |||
[source, java] | |||
.... | |||
declare precedence: A, B, A ; // error | |||
.... | |||
@@ -2267,6 +2174,7 @@ 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; | |||
@@ -2280,6 +2188,7 @@ 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(); | |||
@@ -2313,12 +2222,14 @@ aspects, say, MyLogging and MyProfiling. Because advice only applies | |||
from concrete aspects, the declare precedence form only matters when | |||
declaring precedence with concrete aspects. So | |||
[source, java] | |||
.... | |||
declare precedence: Logging, Profiling; | |||
.... | |||
has no effect, but both | |||
[source, java] | |||
.... | |||
declare precedence: MyLogging, MyProfiling; | |||
declare precedence: Logging+, Profiling+; | |||
@@ -2526,6 +2437,7 @@ All advice runs in the context of an aspect instance, but it is possible | |||
to write a piece of advice with a pointcut that picks out a join point | |||
that must occur before asopect instantiation. For example: | |||
[source, java] | |||
.... | |||
public class Client | |||
{ | |||
@@ -2574,6 +2486,7 @@ private or protected resources of other types. To allow this, aspects | |||
may be declared `privileged`. Code in priviliged aspects has access to | |||
all members, even private ones. | |||
[source, java] | |||
.... | |||
class C { | |||
private int i = 0; | |||
@@ -2594,6 +2507,7 @@ If a privileged aspect can access multiple versions of a particular | |||
member, then those that it could see if it were not privileged take | |||
precedence. For example, in the code | |||
[source, java] | |||
.... | |||
class C { | |||
private int i = 0; |
@@ -34,6 +34,7 @@ tells how. | |||
extracts samples of the following form from any "source" file (currently | |||
source, html, text, and shell scripts): | |||
[source, text] | |||
.... | |||
... some text, possibly including @author tags | |||
{comment} START-SAMPLE [anchorName] [anchor title] {end-comment} | |||
@@ -63,6 +64,7 @@ indented only once in the source code, even though they might normally | |||
be indented more. | |||
** In AspectJ, indent advice pointcuts beyond the block code: | |||
+ | |||
[source, java] | |||
.... | |||
before() : call(!public * com.company.library..*.*(String,..)) | |||
&& within(Runnable+) { // indent once more than code | |||
@@ -107,6 +109,7 @@ suffixes necessary for clarity and to make sure there are unique titles | |||
for each test. E.g., for a sample with the anchor | |||
"`language-initialization`", | |||
+ | |||
[source, xml] | |||
.... | |||
<ajc-test | |||
dir="common" | |||
@@ -124,6 +127,7 @@ compile. | |||
by verifying that the error message is produced, checking either or both | |||
of the line number and the message text. E.g., | |||
+ | |||
[source, xml] | |||
.... | |||
<compile files="declares/Declares.java, {others}" | |||
<message kind="error" line="15" text="Factory"/> | |||
@@ -135,6 +139,7 @@ message and the target code in sync. You can help with this by adding a | |||
comment in the target code so people editing the code know not to fix or | |||
move the code. E.g., | |||
+ | |||
[source, java] | |||
.... | |||
void spawn() { | |||
new Thread(this, toString()).start(); // KEEP CE 15 declares-factory | |||
@@ -151,6 +156,7 @@ make it easier to find the test that will break if the code is modified. | |||
If the code is broken (e.g., if it no longer works in the latest version | |||
of AspectJ), then prefix SAMPLE with BROKEN in the tag: | |||
[source, text] | |||
.... | |||
{comment} START-BROKEN-SAMPLE ... | |||
... sample code ... |
@@ -37,6 +37,7 @@ up ajc as the compiler, do the following before starting Tomcat: | |||
tell Ant to use `ajc` by setting the compiler property to the AspectJ | |||
compiler adapter: | |||
+ | |||
[source, xml] | |||
.... | |||
<servlet> | |||
<servlet-name>jsp</servlet-name> |