Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>tags/V1_9_21_1
@@ -14,28 +14,28 @@ AspectJ, we recommend you start by reading the programming guide. | |||
ATTENTION: Please do not remove blank lines in between 'include::' statements. Otherwise, section numbers in the | |||
table of contents (TOC) can be wrong and the first section of each document missing completely. | |||
//// | |||
include::joinpointsignatures.adoc[] | |||
include::joinpointsignatures.adoc[Join Point Signatures] | |||
include::annotations.adoc[] | |||
include::annotations.adoc[Annotations] | |||
include::generics.adoc[] | |||
include::generics.adoc[Generics] | |||
include::autoboxing.adoc[] | |||
include::autoboxing.adoc[Autoboxing and Unboxing] | |||
include::covariance.adoc[] | |||
include::covariance.adoc[Covariance] | |||
include::varargs.adoc[] | |||
include::varargs.adoc[Varargs] | |||
include::enumeratedtypes.adoc[] | |||
include::enumeratedtypes.adoc[Enumerated Types] | |||
include::pertypewithin.adoc[] | |||
include::pertypewithin.adoc[The `pertypewithin` Aspect Instantiation Model] | |||
include::ataspectj.adoc[] | |||
include::ataspectj.adoc[An Annotation Based Development Style] | |||
include::reflection.adoc[] | |||
include::reflection.adoc[New Reflection Interfaces] | |||
include::miscellaneous.adoc[] | |||
include::miscellaneous.adoc[Other Changes in AspectJ 5] | |||
include::ltw.adoc[] | |||
include::ltw.adoc[Load-Time Weaving] | |||
include::grammar.adoc[] | |||
include::grammar.adoc[A Grammar for the AspectJ 5 Language] |
@@ -210,7 +210,8 @@ is equivalent to... | |||
[source, java] | |||
.... | |||
pointcut someCallWithIfTest(int i) : call(* *.*(int)) && args(i) && if(i > 0); | |||
pointcut someCallWithIfTest(int i) : | |||
call(* *.*(int)) && args(i) && if(i > 0); | |||
.... | |||
and the following is also a valid form: | |||
@@ -321,8 +322,7 @@ annotation style. | |||
.... | |||
@Before("call(* org.aspectprogrammer..*(..)) && this(foo)") | |||
public void callFromFoo(JoinPoint thisJoinPoint, Foo foo) { | |||
System.out.println("Call from Foo: " + foo + " at " | |||
+ thisJoinPoint); | |||
System.out.println("Call from Foo: " + foo + " at " + thisJoinPoint); | |||
} | |||
.... | |||
@@ -331,8 +331,7 @@ is equivalent to... | |||
[source, java] | |||
.... | |||
before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { | |||
System.out.println("Call from Foo: " + foo + " at " | |||
+ thisJoinPoint); | |||
System.out.println("Call from Foo: " + foo + " at " + thisJoinPoint); | |||
} | |||
.... | |||
@@ -341,9 +340,11 @@ Advice that needs all three variables would be declared: | |||
[source, java] | |||
.... | |||
@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") | |||
public void callFromFoo(JoinPoint thisJoinPoint, | |||
JoinPoint.StaticPart thisJoinPointStaticPart, | |||
JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart) { | |||
public void callFromFoo( | |||
JoinPoint thisJoinPoint, | |||
JoinPoint.StaticPart thisJoinPointStaticPart, | |||
JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart | |||
) { | |||
// ... | |||
} | |||
.... | |||
@@ -388,7 +389,7 @@ after() returning(Foo f) : call(Foo+.new(..)) { | |||
} | |||
.... | |||
(Note the use of the "pointcut=" prefix in front of the pointcut | |||
(Note the use of the `pointcut=` prefix in front of the pointcut | |||
expression in the returning case). | |||
After throwing advice works in a similar fashion, using the `throwing` | |||
@@ -460,73 +461,63 @@ public aspect ProceedAspect { | |||
.... | |||
Note that the ProceedingJoinPoint does not need to be passed to the | |||
proceed(..) arguments. | |||
`proceed(..)` arguments. | |||
In code style, the proceed method has the same signature as the advice, | |||
any reordering of actual arguments to the joinpoint that is done in the | |||
advice signature must be respected. Annotation style is different. The | |||
proceed(..) call takes, in this order: | |||
* If 'this()' was used in the pointcut | |||
+ | |||
for binding | |||
+ | |||
, it must be passed first in proceed(..). | |||
* If 'target()' was used in the pointcut | |||
+ | |||
for binding | |||
+ | |||
, it must be passed next in proceed(..) - it will be the first argument | |||
to proceed(..) if this() was not used for binding. | |||
* Finally come | |||
+ | |||
all | |||
+ | |||
the arguments expected at the join point, in the order they are supplied | |||
at the join point. Effectively the advice signature is ignored - it | |||
doesn't matter if a subset of arguments were bound or the ordering was | |||
changed in the advice signature, the proceed(..) calls takes all of them | |||
in the right order for the join point. | |||
Since proceed(..) in this case takes an Object array, AspectJ cannot do | |||
`proceed(..)` call takes, in this order: | |||
* If `this()` was used in the pointcut for binding, it must be passed first in | |||
`proceed(..)`. | |||
* If `target()` was used in the pointcut for binding, it must be passed next in | |||
`proceed(..)` - it will be the first argument to `proceed(..)` if `this()` | |||
was not used for binding. | |||
* Finally come all the arguments expected at the join point, in the order they | |||
are supplied at the join point. Effectively the advice signature is ignored - | |||
it doesn't matter if a subset of arguments were bound or the ordering was | |||
changed in the advice signature, the `proceed(..)` calls takes all of them | |||
in the right order for the join point. | |||
Since `proceed(..)` in this case takes an `Object` array, AspectJ cannot do | |||
as much compile time checking as it can for code style. If the rules | |||
above aren't obeyed then it will unfortunately manifest as a runtime | |||
above aren't obeyed, then it will unfortunately manifest as a runtime | |||
error. | |||
[[ataspectj-itds]] | |||
=== Inter-type Declarations | |||
Inter-type declarations are challenging to support using an annotation | |||
style. For code style aspects compiled with the ajc compiler, the entire | |||
style. For code style aspects compiled with the _ajc_ compiler, the entire | |||
type system can be made aware of inter-type declarations (new | |||
supertypes, new methods, new fields) and the completeness and | |||
correctness of it can be guaranteed. Achieving this with an annotation | |||
style is hard because the source code may simply be compiled with javac | |||
where the type system cannot be influenced and what is compiled must be | |||
'pure java'. | |||
'pure Java'. | |||
AspectJ 1.5.0 introduced @DeclareParents, an attempt to offer something | |||
AspectJ 1.5.0 introduced `@DeclareParents`, an attempt to offer something | |||
like that which is achievable with code style declare parents and the | |||
other intertype declarations (fields, methods, constructors). However, | |||
it has proved too challenging to get close to the expressiveness and | |||
capabilities of code style in this area and effectively @DeclareParents | |||
is offering just a mixin strategy. The definition of mixin I am using | |||
here is that when some interface I is mixed into some target type T then | |||
this means that all the methods from I are created in T and their | |||
capabilities of code style in this area and effectively `@DeclareParents` | |||
is offering just a mixin strategy. The definition of mixin `I` am using | |||
here is that when some `interface I` is mixed into some target type `T` then | |||
this means that all the methods from `I` are created in `T` and their | |||
implementations are simple forwarding methods that call a delegate which | |||
that provides an implementation of I. | |||
that provides an implementation of `I`. | |||
The next section covers @DeclareParents but AspectJ 1.6.4 introduces | |||
@DeclareMixin - an improved approach to defining a mixin and the choice | |||
The next section covers `@DeclareParents` but AspectJ 1.6.4 introduces | |||
`@DeclareMixin` - an improved approach to defining a mixin and the choice | |||
of a different name for the annotation will hopefully alleviate some of | |||
the confusion about why @DeclareParents just doesn't offer the same | |||
semantics as the code style variant. Offering @DeclareMixin also gives | |||
the confusion about why `@DeclareParents` just doesn't offer the same | |||
semantics as the code style variant. Offering `@DeclareMixin` also gives | |||
code style developers a new tool for a simple mixin whereas previously | |||
they would have avoided @DeclareParents thinking what it could only do | |||
they would have avoided `@DeclareParents`, thinking what it could only do | |||
was already achievable with code style syntax. | |||
The defaultImpl attribute of @DeclareParents may become deprecated if | |||
@DeclareMixin proves popular, leaving @DeclareParents purely as a way to | |||
The `defaultImpl` attribute of `@DeclareParents` may become deprecated if | |||
`@DeclareMixin` proves popular, leaving `@DeclareParents` purely as a way to | |||
introduce a marker interface. | |||
[[atDeclareParents]] | |||
@@ -595,13 +586,13 @@ public class MoodIndicator { | |||
This is very similar to the mixin mechanism supported by AspectWerkz. | |||
The effect of the `@DeclareParents` annotation is equivalent to a | |||
declare parents statement that all types matching the type pattern | |||
implement the given interface (in this case Moody). Each method declared | |||
implement the given interface (in this case `Moody`). Each method declared | |||
in the interface is treated as an inter-type declaration. Note how this | |||
scheme operates within the constraints of Java type checking and ensures | |||
that `this` has access to the exact same set of members as in the code | |||
style example. | |||
Note that it is illegal to use the @DeclareParents annotation on an | |||
Note that it is illegal to use the `@DeclareParents` annotation on an | |||
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. | |||
@@ -680,7 +671,7 @@ and a method that returns the mood. Within the body of the inter-type | |||
declared method `getMoody`, the type of `this` is `Moody` (the target | |||
type of the inter-type declaration). | |||
Using the annotation style this aspect can be written: | |||
Using the annotation style, this aspect can be written: | |||
[source, java] | |||
.... | |||
@@ -779,7 +770,7 @@ public class Foo { | |||
Although the interface type is usually determined purely from the return | |||
type of the factory method, it can be specified in the annotation if | |||
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 | |||
multiple other interfaces and only a couple of them (`I` and `J`) should be | |||
mixed into any matching targets: | |||
[source, java] | |||
@@ -805,14 +796,13 @@ delegate forwarding methods created in the matched target type. | |||
=== Declare statements | |||
The previous section on inter-type declarations covered the case of | |||
declare parents ... implements. The 1.5.0 release of AspectJ 5 does not | |||
support annotation style declarations for declare parents ... extends | |||
and declare soft (programs with these declarations would not in general | |||
`declare parents ...` implements. The 1.5.0 release of AspectJ 5 does not | |||
support annotation style declarations for `declare parents ... extends` | |||
and `declare soft` (programs with these declarations would not in general | |||
be compilable by a regular Java 5 compiler, reducing the priority of | |||
their implementation). These may be supported in a future release. | |||
Declare annotation is also not supported in the 1.5.0 release of AspectJ | |||
5. | |||
Declare annotation is also not supported in the 1.5.0 release of AspectJ 5. | |||
Declare precedence _is_ supported. For declare precedence, use the | |||
`@DeclarePrecedence` annotation as in the following example: | |||
@@ -821,7 +811,6 @@ Declare precedence _is_ supported. For declare precedence, use the | |||
.... | |||
public aspect SystemArchitecture { | |||
declare precedence : Security*, TransactionSupport, Persistence; | |||
// ... | |||
} | |||
.... | |||
@@ -871,12 +860,12 @@ static final String badIFooImplementors = "Only foo types can implement IFoo"; | |||
@DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)") | |||
static final String badIFooImplementorsCorrupted = getMessage(); | |||
static String getMessage() { | |||
return "Only foo types can implement IFoo " + System.currentTimeMillis(); | |||
return "Only foo types can implement IFoo " + System.currentTimeMillis(); | |||
} | |||
.... | |||
[[ataspectj-aspectof]] | |||
=== aspectOf() and hasAspect() methods | |||
=== `aspectOf()` and `hasAspect()` methods | |||
A central part of AspectJ's programming model is that aspects written | |||
using the code style and compiled using ajc support `aspectOf` and |
@@ -5,8 +5,8 @@ | |||
=== Autoboxing and Unboxing in Java 5 | |||
Java 5 (and hence AspectJ 1.5) supports automatic conversion of | |||
primitive types (int, float, double etc.) to their object equivalents | |||
(Integer, Float, Double,...) in assignments and method and constructor | |||
primitive types (`int`, `float`, `double` etc.) to their object equivalents | |||
(`Integer`, `Float`, `Double` etc.) in assignments and method and constructor | |||
invocations. This conversion is know as autoboxing. | |||
Java 5 also supports automatic unboxing, where wrapper types are | |||
@@ -18,9 +18,8 @@ For example: | |||
[source, java] | |||
.... | |||
int i = 0; | |||
i = new Integer(5); // auto-unboxing | |||
Integer i2 = 5; // autoboxing | |||
i = new Integer(5); // auto-unboxing | |||
Integer i2 = 5; // autoboxing | |||
.... | |||
[[autoboxing-in-aspectj5]] | |||
@@ -43,13 +42,13 @@ autoboxing and unboxing in determining argument matching. In other | |||
words, `args(Integer)` will match any join point at which there is a | |||
single argument of type `Integer` or of type `int`. | |||
* args(Integer) and args(int) are equivalent | |||
* args(Float) and args(float) are equivalent | |||
* args(Double) and args(double) are equivalent | |||
* args(Short) and args(short) are equivalent | |||
* args(Byte) and args(byte) are equivalent | |||
* args(Long) and args(long) are equivalent | |||
* args(Boolean) and args(boolean) are equivalent | |||
* `args(Integer)` and `args(int)` are equivalent | |||
* `args(Float)` and `args(float)` are equivalent | |||
* `args(Double)` and `args(double)` are equivalent | |||
* `args(Short)` and `args(short)` are equivalent | |||
* `args(Byte)` and `args(byte)` are equivalent | |||
* `args(Long)` and `args(long)` are equivalent | |||
* `args(Boolean)` and `args(boolean)` are equivalent | |||
Autoboxing and unboxing are also applied when binding pointcut or advice | |||
parameters, for example: | |||
@@ -59,7 +58,7 @@ parameters, for example: | |||
pointcut foo(int i) : args(i); | |||
before(Integer i) : foo(i) { | |||
... | |||
// ... | |||
} | |||
.... | |||
@@ -64,13 +64,13 @@ Following the join point matching rules given in xref:joinpointsignatures.adoc#j | |||
`call(A B.whoAreYou())`:: | |||
Does not match anything - neither of the call join points has a | |||
signature matched by this pattern. A lint warning is given for the | |||
call `a.whoAreYou()` ("does not match because declaring type is A, if | |||
match required use target(B)"). | |||
call `a.whoAreYou()` ("does not match because declaring type is `A`, if | |||
match required use ``target(B)``"). | |||
`call(A+ B.whoAreYou())`:: | |||
Matches the call to `b.whoAreYou()` since the signature pattern | |||
matches the signature `B B.whoAreYou()`. A lint warning is given for | |||
the call `a.whoAreYou()` ("does not match because declaring type is A, | |||
if match required use target(B)"). | |||
the call `a.whoAreYou()` ("does not match because declaring type is `A`, | |||
if match required use ``target(B)``"). | |||
`call(B A.whoAreYou())`:: | |||
Does not match anything since neither join point has a signature | |||
matched by this pattern. |
@@ -31,7 +31,7 @@ does. Because of the special restrictions Java 5 places around | |||
enumerated types, AspectJ makes the following additional restrictions: | |||
* You cannot use declare parents to change the super type of an enum. | |||
* You cannot use declare parents to declare java.lang.Enum as the parent | |||
* You cannot use declare parents to declare `java.lang.Enum` as the parent | |||
of any type. | |||
* You cannot make inter-type constructor declarations on an enum. | |||
* You cannot extend the set of values in an enum via any ITD-like |
@@ -251,80 +251,20 @@ defines the rules for determing the erasure of a type as follows. | |||
Let `|T|` represent the erasure of some type `T`. Then: | |||
The erasure of a parameterized type | |||
* The erasure of a parameterized type `T<T1,...,Tn>` is `|T|`. | |||
For example, the erasure of `List<String>` is `List`. | |||
T<T1,...,Tn> | |||
* The erasure of a nested type `T.C` is `|T|.C`. | |||
For example, the erasure of the nested type `Foo<T>.Bar` is `Foo.Bar`. | |||
is | |||
* The erasure of an array type `T[]` is `|T|[]`. | |||
For example, the erasure of `List<String>[]` is `List[]`. | |||
|T| | |||
* The erasure of a type variable is its leftmost bound. | |||
For example, the erasure of a type variable `P` is `Object`, | |||
and the erasure of a type variable `N extends Number` is `Number`. | |||
. For example, the erasure of | |||
List<String> | |||
is | |||
List | |||
. | |||
The erasure of a nested type | |||
T.C | |||
is | |||
|T|.C | |||
. For example, the erasure of the nested type | |||
Foo<T>.Bar | |||
is | |||
Foo.Bar | |||
. | |||
The erasure of an array type | |||
T[] | |||
is | |||
|T|[] | |||
. For example, the erasure of | |||
List<String>[] | |||
is | |||
List[] | |||
. | |||
The erasure of a type variable is its leftmost bound. For example, the | |||
erasure of a type variable | |||
P | |||
is | |||
Object | |||
, and the erasure of a type variable | |||
N extends Number | |||
is | |||
Number | |||
. | |||
The erasure of every other type is the type itself | |||
* The erasure of every other type is the type itself. | |||
Applying these rules to the earlier examples, we find that the methods | |||
defined in `Utils` can be matched by a signature pattern matching | |||
@@ -409,9 +349,7 @@ the methods: | |||
.... | |||
class C { | |||
public void foo(List<? extends Number> listOfSomeNumberType) {} | |||
public void bar(List<?> listOfSomeType) {} | |||
public void goo(List<Double> listOfDoubles) {} | |||
} | |||
.... | |||
@@ -508,24 +446,26 @@ public class C { | |||
.... | |||
`args(List)`:: | |||
will match an execution or call join point for any of these methods | |||
will match an execution or call join point for any of these methods | |||
`args(List<String>)`:: | |||
will match an execution or call join point for `foo`. | |||
will match an execution or call join point for `foo`. | |||
`args(List<Double>)`:: | |||
matches an execution or call join point for `bar`, and _may_ match at | |||
an execution or call join point for `goo` since it is legitimate to | |||
pass an object of type `List<Double>` to a method expecting a | |||
`List<? extends Number>`. | |||
+ | |||
In this situation a runtime test would normally be applied to | |||
ascertain whether or not the argument was indeed an instance of the | |||
required type. However, in the case of parameterized types such a test | |||
is not possible and therefore AspectJ 5 considers this a match, but | |||
issues an _unchecked_ warning. For example, compiling the aspect `A` | |||
below with the class `C` produces the compilation warning: "unchecked | |||
match of List<Double> with List<? extends Number> when argument is an | |||
instance of List at join point method-execution(void C.goo(List<? | |||
extends Number>)) [Xlint:uncheckedArgument]"; | |||
matches an execution or call join point for `bar`, and _may_ match at | |||
an execution or call join point for `goo` since it is legitimate to | |||
pass an object of type `List<Double>` to a method expecting a | |||
`List<? extends Number>`. | |||
+ | |||
In this situation, a runtime test would normally be applied to | |||
ascertain whether or not the argument was indeed an instance of the | |||
required type. However, in the case of parameterized types such a test | |||
is not possible and therefore AspectJ 5 considers this a match, but | |||
issues an _unchecked_ warning. For example, compiling the aspect `A` | |||
below with the class `C` produces the compilation warning: `unchecked | |||
match of List<Double> with List<? extends Number> when argument is an | |||
instance of List at join point method-execution(void C.goo(List<? | |||
extends Number>)) [Xlint:uncheckedArgument]`; | |||
[source, java] | |||
.... | |||
@@ -622,9 +562,9 @@ aspect A { | |||
From the signature of `foo` all we know is that the runtime argument | |||
will be an instance of `Object`.Compiling this program gives the | |||
unchecked argument warning: "unchecked match of List<? extends Number> | |||
unchecked argument warning: `unchecked match of List<? extends Number> | |||
with List when argument is an instance of List at join point | |||
method-execution(void C.foo(Object)) [Xlint:uncheckedArgument]". The | |||
method-execution(void C.foo(Object)) [Xlint:uncheckedArgument]`. The | |||
advice will not execute at the call join point for `c.foo("hi")` since | |||
`String` is not an instance of `List`. The advice _will_ execute at the | |||
call join points for `c.foo(ls)` and `c.foo(ld)` since in both cases the | |||
@@ -685,9 +625,7 @@ Given the class | |||
.... | |||
public class C { | |||
public List<String> foo(List<String> listOfStrings) {...} | |||
public List<Double> bar(List<Double> listOfDoubles) {...} | |||
public List<? extends Number> goo(List<? extends Number> listOfSomeNumberType) {...} | |||
} | |||
.... | |||
@@ -764,8 +702,8 @@ specification: | |||
`<T extends Number> T Utils.max(T first, T second) {...}`:: | |||
Declares a generic instance method `max` on the class `Util`. The | |||
`max` method takes two arguments, `first` and `second` which must both | |||
be of the same type (and that type must be Number or a subtype of | |||
Number) and returns an instance of that type. | |||
be of the same type (and that type must be `Number` or a subtype of | |||
`Number`) and returns an instance of that type. | |||
`static <E> E Utils.first(List<E> elements) {...}`:: | |||
Declares a static generic method `first` on the class `Util`. The | |||
`first` method takes a list of elements of some type, and returns an | |||
@@ -965,52 +903,40 @@ could declare the concrete aspect: | |||
.... | |||
public aspect ASTNodeContainment extends ParentChildRelationship<ASTNode,ASTNode> { | |||
before(ASTNode parent, ASTNode child) : addingChild(parent, child) { | |||
... | |||
// ... | |||
} | |||
} | |||
.... | |||
As a result of this declaration, `ASTNode` gains members: | |||
List<ASTNode> children | |||
ASTNode parent | |||
List<ASTNode>getChildren() | |||
ASTNode getParent() | |||
void addChild(ASTNode child) | |||
void removeChild(ASTNode child) | |||
void setParent(ASTNode parent) | |||
* `List<ASTNode> children` | |||
* `ASTNode parent` | |||
* `List<ASTNode>getChildren()` | |||
* `ASTNode getParent()` | |||
* `void addChild(ASTNode child)` | |||
* `void removeChild(ASTNode child)` | |||
* `void setParent(ASTNode parent)` | |||
In a system managing orders, we could declare the concrete aspect: | |||
[source, java] | |||
.... | |||
public aspect OrderItemsInOrders extends ParentChildRelationship<Order, OrderItem> { | |||
} | |||
public aspect OrderItemsInOrders extends ParentChildRelationship<Order, OrderItem> {} | |||
.... | |||
As a result of this declaration, `Order` gains members: | |||
List<OrderItem> children | |||
List<OrderItem> getChildren() | |||
void addChild(OrderItem child) | |||
void removeChild(OrderItem child) | |||
* `List<OrderItem> children` | |||
* `List<OrderItem> getChildren()` | |||
* `void addChild(OrderItem child)` | |||
* `void removeChild(OrderItem child)` | |||
and `OrderItem` gains members: | |||
Order parent | |||
Order getParent() | |||
void setParent(Order parent) | |||
* `Order parent` | |||
* `Order getParent()` | |||
* `void setParent(Order parent)` | |||
A second example of an abstract aspect, this time for handling | |||
exceptions in a uniform manner, is shown below: |
@@ -5,22 +5,24 @@ | |||
.... | |||
=== type patterns === | |||
TypePattern := SimpleTypePattern | | |||
'!' TypePattern | | |||
'(' AnnotationPattern? TypePattern ')' | |||
TypePattern '&&' TypePattern | | |||
TypePattern '||' TypePattern | |||
TypePattern := | |||
SimpleTypePattern | | |||
'!' TypePattern | | |||
'(' AnnotationPattern? TypePattern ')' | |||
TypePattern '&&' TypePattern | | |||
TypePattern '||' TypePattern | |||
SimpleTypePattern := DottedNamePattern '+'? '[]'* | |||
DottedNamePattern := FullyQualifiedName RestOfNamePattern? | | |||
'*' NotStarNamePattern? | |||
DottedNamePattern := | |||
FullyQualifiedName RestOfNamePattern? | | |||
'*' NotStarNamePattern? | |||
RestOfNamePattern := '..' DottedNamePattern | | |||
'*' NotStarNamePattern? | |||
RestOfNamePattern := '..' DottedNamePattern | '*' NotStarNamePattern? | |||
NotStarNamePattern := FullyQualifiedName RestOfNamePattern? | | |||
'..' DottedNamePattern | |||
NotStarNamePattern := | |||
FullyQualifiedName RestOfNamePattern? | | |||
'..' DottedNamePattern | |||
FullyQualifiedName := JavaIdentifierCharacter+ ('.' JavaIdentifierCharacter+)* | |||
@@ -28,22 +30,21 @@ FullyQualifiedName := JavaIdentifierCharacter+ ('.' JavaIdentifierCharacter+)* | |||
AnnotationPattern := '!'? '@' AnnotationTypePattern AnnotationPattern* | |||
AnnotationTypePattern := FullyQualifiedName | | |||
'(' TypePattern ')' | |||
AnnotationTypePattern := FullyQualifiedName | '(' TypePattern ')' | |||
=== signature patterns === | |||
-- field -- | |||
FieldPattern := | |||
AnnotationPattern? FieldModifiersPattern? | |||
TypePattern (TypePattern DotOrDotDot)? SimpleNamePattern | |||
AnnotationPattern? FieldModifiersPattern? | |||
TypePattern (TypePattern DotOrDotDot)? SimpleNamePattern | |||
FieldModifiersPattern := '!'? FieldModifier FieldModifiersPattern* | |||
FieldModifier := 'public' | 'private' | 'protected' | 'static' | | |||
'transient' | 'final' | |||
FieldModifier := | |||
'public' | 'private' | 'protected' | 'static' | | |||
'transient' | 'final' | |||
DotOrDotDot := '.' | '..' | |||
@@ -52,18 +53,20 @@ SimpleNamePattern := JavaIdentifierChar+ ('*' SimpleNamePattern)? | |||
-- method -- | |||
MethodPattern := | |||
AnnotationPattern? MethodModifiersPattern? TypePattern | |||
(TypePattern DotOrDotDot)? SimpleNamePattern | |||
'(' FormalsPattern ')' ThrowsPattern? | |||
AnnotationPattern? MethodModifiersPattern? TypePattern | |||
(TypePattern DotOrDotDot)? SimpleNamePattern | |||
'(' FormalsPattern ')' ThrowsPattern? | |||
MethodModifiersPattern := '!'? MethodModifier MethodModifiersPattern* | |||
MethodModifier := 'public' | 'private' | 'protected' | 'static' | | |||
'synchronized' | 'final' | |||
MethodModifier := | |||
'public' | 'private' | 'protected' | 'static' | | |||
'synchronized' | 'final' | |||
FormalsPattern := '..' (',' FormalsPatternAfterDotDot)? | | |||
OptionalParensTypePattern (',' FormalsPattern)* | | |||
TypePattern '...' | |||
FormalsPattern := | |||
'..' (',' FormalsPatternAfterDotDot)? | | |||
OptionalParensTypePattern (',' FormalsPattern)* | | |||
TypePattern '...' | |||
FormalsPatternAfterDotDot := | |||
OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* | | |||
@@ -76,27 +79,28 @@ TypePatternList := TypePattern (',' TypePattern)* | |||
-- constructor -- | |||
ConstructorPattern := | |||
AnnotationPattern? ConstructorModifiersPattern? | |||
(TypePattern DotOrDotDot)? 'new' '(' FormalsPattern ')' | |||
ThrowsPattern? | |||
AnnotationPattern? ConstructorModifiersPattern? | |||
(TypePattern DotOrDotDot)? 'new' '(' FormalsPattern ')' | |||
ThrowsPattern? | |||
ConstructorModifiersPattern := '!'? ConstructorModifier ConstructorModifiersPattern* | |||
ConstructorModifiersPattern := | |||
'!'? ConstructorModifier ConstructorModifiersPattern* | |||
ConstructorModifier := 'public' | 'private' | 'protected' | |||
=== Pointcuts === | |||
PointcutPrimitive := | |||
Call | Execution | Get | Set | Handler | | |||
Initialization | PreInitialization | | |||
StaticInitialization | AdviceExecution | | |||
This | Target | Args | CFlow | CFlowBelow | | |||
Within | WithinCode | If | | |||
AnnotationPointcut | |||
AnnotationPointcut := AtAnnotation | AtThis | AtTarget | | |||
AtWithin | AtWithinCode | AtArgs | |||
Call | Execution | Get | Set | Handler | | |||
Initialization | PreInitialization | | |||
StaticInitialization | AdviceExecution | | |||
This | Target | Args | CFlow | CFlowBelow | | |||
Within | WithinCode | If | | |||
AnnotationPointcut | |||
AnnotationPointcut := | |||
AtAnnotation | AtThis | AtTarget | | |||
AtWithin | AtWithinCode | AtArgs | |||
Call := 'call' '(' MethodOrConstructorPattern ')' | |||
@@ -124,13 +128,13 @@ TypeOrIdentifier := FullyQualifiedName ('[' ']')* | Identifier | |||
Identifier := JavaIdentifierChar+ | |||
FormalsOrIdentifiersPattern := | |||
'..' (',' FormalsOrIdentifiersPatternAfterDotDot)? | | |||
TypeOrIdentifier (',' FormalsOrIdentifiersPattern)* | | |||
'*' (',' FormalsOrIdentifiersPattern)* | |||
'..' (',' FormalsOrIdentifiersPatternAfterDotDot)? | | |||
TypeOrIdentifier (',' FormalsOrIdentifiersPattern)* | | |||
'*' (',' FormalsOrIdentifiersPattern)* | |||
FormalsOrIdentifiersPatternAfterDotDot := | |||
TypeOrIdentifier (',' FormalsOrIdentifiersPatternAfterDotDot)* | | |||
'*' (',' FormalsOrIdentifiersPatternAfterDotDot)* | |||
TypeOrIdentifier (',' FormalsOrIdentifiersPatternAfterDotDot)* | | |||
'*' (',' FormalsOrIdentifiersPatternAfterDotDot)* | |||
AtAnnotation := '@annotation' '(' AnnotationOrIdentifier ')' | |||
AtThis := '@this' '(' AnnotationOrIdentifer ')' | |||
@@ -143,31 +147,32 @@ AnnotationOrIdentifier := FullyQualifiedName | Identifier | |||
AtArgs := '@args' '(' AnnotationsOrIdentifiersPattern ')' | |||
AnnotationsOrIdentifiersPattern := | |||
'..' (',' AnnotationsOrIdentifiersPatternAfterDotDot)? | | |||
AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPattern)* | | |||
'*' (',' AnnotationsOrIdentifiersPattern)* | |||
'..' (',' AnnotationsOrIdentifiersPatternAfterDotDot)? | | |||
AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPattern)* | | |||
'*' (',' AnnotationsOrIdentifiersPattern)* | |||
AnnotationsOrIdentifiersPatternAfterDotDot := | |||
AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPatternAfterDotDot)* | | |||
'*' (',' AnnotationsOrIdentifiersPatternAfterDotDot)* | |||
AnnotationOrIdentifier (',' AnnotationsOrIdentifiersPatternAfterDotDot)* | | |||
'*' (',' AnnotationsOrIdentifiersPatternAfterDotDot)* | |||
PointcutDeclaration := PointcutModifiers? 'pointcut' Identifier Formals | |||
':' PointcutExpression | |||
PointcutDeclaration := | |||
PointcutModifiers? 'pointcut' Identifier Formals ':' PointcutExpression | |||
PointcutModifiers := PointcutModifier* | |||
PointcutModifier := 'public' | 'private' | 'protected' | 'abstract' | |||
PointcutModifier := 'public' | 'private' | 'protected' | 'abstract' | |||
Formals := '(' ParamList? ')' | |||
ParamList := FullyQualifiedName Identifier (',' ParamList)* | |||
ReferencePointcut := (FullyQualifiedName '.')? Identifier Formals | |||
PointcutExpression := (PointcutPrimitive | ReferencePointcut) | | |||
'!' PointcutExpression | | |||
'(' PointcutExpression ')' | | |||
PointcutExpression '&&' PointcutExpression | | |||
PointcutExpression '||' PointcutExpression | |||
PointcutExpression := | |||
(PointcutPrimitive | ReferencePointcut) | | |||
'!' PointcutExpression | | |||
'(' PointcutExpression ')' | | |||
PointcutExpression '&&' PointcutExpression | | |||
PointcutExpression '||' PointcutExpression | |||
=== Advice === | |||
@@ -4,5 +4,5 @@ | |||
[[ltw-introduction]] | |||
=== Introduction | |||
See Developer's Guide for information on load-time weaving support in | |||
AspectJ 5. | |||
See xref:../devGuideDB/ltw.adoc#ltw[Developer's Guide] for information on | |||
load-time weaving support in AspectJ 5. |
@@ -10,8 +10,9 @@ example, AspectJ 1.2.1 does not allow: | |||
[source, java] | |||
.... | |||
pointcut foo(Foo foo) : (execution(* *(..)) && this(foo) ) || | |||
(set(* *) && target(foo)); | |||
pointcut foo(Foo foo) : | |||
(execution(* *(..)) && this(foo) ) || | |||
(set(* *) && target(foo)); | |||
.... | |||
whereas this expression is permitted in AspectJ 5. Each context variable | |||
@@ -33,7 +34,8 @@ XLint warning will be issued: | |||
.... | |||
declare soft : SomeRuntimeException : execution(* *(..)); | |||
>> "SomeRuntimeException will not be softened as it is already a RuntimeException" [XLint:runtimeExceptionNotSoftened] | |||
// "SomeRuntimeException will not be softened as it is already a | |||
// RuntimeException" [XLint:runtimeExceptionNotSoftened] | |||
.... | |||
This XLint message can be controlled by setting the |
@@ -1,5 +1,5 @@ | |||
[[pertypewithin]] | |||
== The pertypewithin Aspect Instantiation Model | |||
== The `pertypewithin` Aspect Instantiation Model | |||
AspectJ 5 defines a new per-clause type for aspect instantiation: | |||
`pertypewithin`. Unlike the other per-clauses, `pertypewithin` takes a |
@@ -8,7 +8,7 @@ reflection APIs are only supported when running under Java 5 and for | |||
code compiled by the AspectJ 5 compiler at target level 1.5. | |||
[[reflection_api]] | |||
=== Using AjTypeSystem | |||
=== Using `AjTypeSystem` | |||
The starting point for using the reflection apis is | |||
`org.aspectj.lang.reflect.AjTypeSystem` which provides the method |
@@ -5,12 +5,11 @@ | |||
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: | |||
an ellipsis (`...`) in the method signature as shown: | |||
[source, java] | |||
.... | |||
public void foo(int i, String... strings) { | |||
} | |||
public void foo(int i, String... strings) {} | |||
.... | |||
A method or constructor may take at most one variable length argument, | |||
@@ -69,13 +68,14 @@ last argument position of a method or constructor signature. | |||
[source, text] | |||
.... | |||
FormalsPattern := '..' (',' FormalsPatternAfterDotDot)? | | |||
OptionalParensTypePattern (',' FormalsPattern)* | | |||
TypePattern '...' | |||
FormalsPattern := | |||
'..' (',' FormalsPatternAfterDotDot)? | | |||
OptionalParensTypePattern (',' FormalsPattern)* | | |||
TypePattern '...' | |||
FormalsPatternAfterDotDot := | |||
OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* | | |||
TypePattern '...' | |||
OptionalParensTypePattern (',' FormalsPatternAfterDotDot)* | | |||
TypePattern '...' | |||
.... | |||
Method and constructor patterns are used in the `call`, `execution`, | |||
@@ -84,16 +84,16 @@ designators. Some examples of usage follow: | |||
`call(* org.xyz.*.*(int, String...))`:: | |||
Matches a call join point for a call to a method defined in the | |||
`org.xyz` package, taking an `int` and a `String vararg`. | |||
`org.xyz` package, taking an `int` and a `String` _vararg_. | |||
`execution(* org.xyz.*.*(Integer...))`:: | |||
Matches an execution join point for the execution of a method defined | |||
in the `org.xyz` package, taking an `Integer vararg`. | |||
in the `org.xyz` package, taking an `Integer` _vararg_. | |||
`initialization(org.xyz.*.new((Foo || Goo)...))`:: | |||
Matches the initialization join point for the construction of an | |||
object in the `org.xyz` package via a constructor taking either a | |||
variable number of `Foo` parameters or a variable number of `Goo` | |||
parameters. (This example illustrating the use of a type pattern with | |||
...). | |||
`...`). | |||
A variable argument parameter and an array parameter are treated as | |||
distinct signature elements, so given the method definitions: | |||
@@ -118,8 +118,7 @@ pointcut designator. Given a method | |||
[source, java] | |||
.... | |||
public void foo(int i, String... strings) { | |||
} | |||
public void foo(int i, String... strings) {} | |||
.... | |||
The call or execution join points for `foo` will be matched by the | |||
@@ -143,7 +142,7 @@ designator, you also cannot use the varargs syntax to declare advice | |||
parameters. | |||
Note: the proposal in this section does not allow you to distinguish | |||
between a join point with a signature (int, String...) and a join point | |||
with a signature (int, String[]) based _solely_ on the use of the `args` | |||
between a join point with a signature `(int, String...)` and a join point | |||
with a signature `(int, String[])` based _solely_ on the use of the `args` | |||
pointcut designator. If this distinction is required, `args` can always | |||
be coupled with `call` or `execution`. |
@@ -200,9 +200,9 @@ Pointcuts pick out these join points. For example, the pointcut | |||
[source, java] | |||
.... | |||
pointcut setter(): target(Point) && | |||
(call(void setX(int)) || | |||
call(void setY(int))); | |||
pointcut setter(): | |||
target(Point) && | |||
(call(void setX(int)) || call(void setY(int))); | |||
.... | |||
picks out each call to `setX(int)` or `setY(int)` when called on an | |||
@@ -242,8 +242,8 @@ 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()))` | |||
Pointcuts compose through the operations `or` ("`||`"), `and` ("`&&`") | |||
and `not` ("`!`"). | |||
Pointcuts compose through the operations `OR` (`||`), `ANT` (`&&`) | |||
and `NOT` (`!`). | |||
* It is possible to use wildcards. So | |||
[arabic] | |||
@@ -272,9 +272,7 @@ so long as it takes exactly two ``int``s as arguments. | |||
. `target(Point) && call(int *())` | |||
. `call(* *(..)) && (within(Line) || within(Point))` | |||
. `within(*) && execution(*.new(int))` | |||
. ` | |||
!this(Point) && call(int *(..)) | |||
` | |||
. `!this(Point) && call(int *(..))` | |||
+ | |||
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 | |||
@@ -287,7 +285,7 @@ on negations of modifiers. For example, you can say: | |||
[arabic] | |||
. `call(public * *(..))` | |||
. `execution(!static * *(..))` | |||
. ` execution(public !static * *(..))` | |||
. `execution(public !static * *(..))` | |||
+ | |||
which means (1) any call to a public method, (2) any execution of a | |||
non-static method, and (3) any execution of a public, non-static method. | |||
@@ -319,12 +317,12 @@ number of differences: | |||
Firstly, the lexical pointcut declarations `within` and `withincode` | |||
match differently. At a call join point, the enclosing code is that of | |||
the call site. This means that `call(void m()) | |||
&& withincode(void m())` will only capture directly recursive | |||
the call site. This means that `call(void m()) && withincode(void m())` | |||
will only capture directly recursive | |||
calls, for example. At an execution join point, however, the program is | |||
already executing the method, so the enclosing code is the method | |||
itself: `execution(void m()) | |||
&& withincode(void m())` is the same as `execution(void m())`. | |||
itself: `execution(void m()) && withincode(void m())` is the same as | |||
`execution(void m())`. | |||
Secondly, the call join point does not capture super calls to non-static | |||
methods. This is because such super calls are different in Java, since | |||
@@ -346,7 +344,7 @@ pointcuts. This composition can be somewhat confusing when used with | |||
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: | |||
points picked out by `P`. So, pictorially: | |||
[source, text] | |||
.... | |||
@@ -356,9 +354,8 @@ P --------------------- | |||
\ | |||
.... | |||
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... | |||
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] | |||
.... | |||
@@ -374,12 +371,11 @@ Q -------------\------- | |||
\ \ | |||
.... | |||
Note that <P> and <Q> might not have any join points in common... but | |||
Note that `P` and `Q` might not have any join points in common... but | |||
their control flows might have join points in common. | |||
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>. | |||
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] | |||
.... | |||
@@ -389,10 +385,9 @@ P && Q ------------------- | |||
\ | |||
.... | |||
and if there are _no_ join points that are both picked by <P> and picked | |||
out by <Q>, then there's no chance that there are any join points in the | |||
control flow of `(P && | |||
Q)`. | |||
and if there are _no_ join points that are both picked by `P` and picked | |||
out by `Q`, then there's no chance that there are any join points in the | |||
control flow of `(P && Q)`. | |||
Here's some code that expresses this. | |||
@@ -437,23 +432,23 @@ Consider again the first pointcut definition in this chapter: | |||
[source, java] | |||
.... | |||
pointcut setter(): target(Point) && | |||
(call(void setX(int)) || | |||
call(void setY(int))); | |||
pointcut setter(): | |||
target(Point) && | |||
(call(void setX(int)) || call(void setY(int))); | |||
.... | |||
As we've seen, this pointcut picks out each call to `setX(int)` or | |||
`setY(int)` methods where the target is an instance of `Point`. The | |||
pointcut is given the name `setters` and no parameters on the left-hand | |||
pointcut is given the name `setter` and no parameters on the left-hand | |||
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)) || | |||
call(void setY(int))); | |||
pointcut setter(Point p): | |||
target(p) && | |||
(call(void setX(int)) || call(void setY(int))); | |||
.... | |||
This version picks out exactly the same join points. But in this | |||
@@ -469,13 +464,14 @@ defining pointcut parameters: | |||
[source, java] | |||
.... | |||
pointcut testEquality(Point p): target(Point) && | |||
args(p) && | |||
call(boolean equals(Object)); | |||
pointcut testEquality(Point p): | |||
target(Point) && | |||
args(p) && | |||
call(boolean equals(Object)); | |||
.... | |||
This pointcut also has a parameter of type `Point`. Similar to the | |||
`setters` pointcut, this means that anyone using this pointcut has | |||
`setter` pointcut, this means that anyone using this pointcut has | |||
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 | |||
@@ -486,19 +482,20 @@ pointcut definition that would expose target `Point p1` and argument | |||
[source, java] | |||
.... | |||
pointcut testEquality(Point p1, Point p2): target(p1) && | |||
args(p2) && | |||
call(boolean equals(Object)); | |||
pointcut testEquality(Point p1, Point p2): | |||
target(p1) && | |||
args(p2) && | |||
call(boolean equals(Object)); | |||
.... | |||
Let's look at another variation of the `setters` pointcut: | |||
Let's look at another variation of the `setter` pointcut: | |||
[source, java] | |||
.... | |||
pointcut setter(Point p, int newval): target(p) && | |||
args(newval) && | |||
(call(void setX(int)) || | |||
call(void setY(int))); | |||
pointcut setter(Point p, int newval): | |||
target(p) && | |||
args(newval) && | |||
(call(void setX(int)) || call(void setY(int))); | |||
.... | |||
In this case, a `Point` object and an `int` value are exposed by the | |||
@@ -514,8 +511,8 @@ following pointcut definition will result in a compilation error: | |||
[source, java] | |||
.... | |||
pointcut badPointcut(Point p1, Point p2): | |||
(target(p1) && call(void setX(int))) || | |||
(target(p2) && call(void setY(int))); | |||
(target(p1) && call(void setX(int))) || | |||
(target(p2) && call(void setY(int))); | |||
.... | |||
because `p1` is only bound when calling `setX`, and `p2` is only bound | |||
@@ -588,11 +585,11 @@ in the definition. Basically there are three kinds of pointcut | |||
designator: kinded, scoping and context: | |||
* Kinded designators are those which select a particular kind of join | |||
point. For example: execution, get, set, call, handler | |||
point. For example: `execution, get, set, call, handler` | |||
* Scoping designators are those which select a group of join points of | |||
interest (of probably many kinds). For example: within, withincode | |||
interest (of probably many kinds). For example: `within, withincode` | |||
* Contextual designators are those that match (and optionally bind) | |||
based on context. For example: this, target, @annotation | |||
based on context. For example: `this, target, @annotation` | |||
A well written pointcut should try and include at least the first two | |||
types (kinded and scoping), whilst the contextual designators may be | |||
@@ -616,13 +613,15 @@ pointcut: | |||
[source, java] | |||
.... | |||
pointcut setter(Point p1, int newval): target(p1) && args(newval) | |||
(call(void setX(int) || | |||
call(void setY(int))); | |||
pointcut setter(Point p1, int newval): | |||
target(p1) && args(newval) | |||
(call(void setX(int) || call(void setY(int))); | |||
before(Point p1, int newval): setter(p1, newval) { | |||
System.out.println("About to set something in " + p1 + | |||
" to the new value " + newval); | |||
System.out.println( | |||
"About to set something in " + p1 + | |||
" to the new value " + newval | |||
); | |||
} | |||
.... | |||
@@ -630,11 +629,14 @@ 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)) || | |||
call(void setY(int))) { | |||
System.out.println("About to set something in " + p1 + | |||
" to the new value " + newval); | |||
before(Point p1, int newval): | |||
target(p1) && args(newval) | |||
(call(void setX(int)) || call(void setY(int))) | |||
{ | |||
System.out.println( | |||
"About to set something in " + p1 + | |||
" to the new value " + newval | |||
); | |||
} | |||
.... | |||
@@ -646,7 +648,7 @@ This before advice runs just before the join points picked out by the | |||
[source, java] | |||
.... | |||
before(Point p, int x): target(p) && args(x) && call(void setX(int)) { | |||
if (!p.assertX(x)) return; | |||
if (!p.assertX(x)) return; | |||
} | |||
.... | |||
@@ -656,8 +658,10 @@ 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(); | |||
after(Point p, int x): | |||
target(p) && args(x) && call(void setX(int)) | |||
{ | |||
if (!p.assertX(x)) throw new PostConditionViolation(); | |||
} | |||
.... | |||
@@ -668,8 +672,10 @@ 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); | |||
after(Point p) returning(int x): | |||
target(p) && call(int getX()) | |||
{ | |||
System.out.println("Returning int value " + x + " for p = " + p); | |||
} | |||
.... | |||
@@ -680,7 +686,9 @@ The advice re-raises the exception after it's done: | |||
[source, java] | |||
.... | |||
after() throwing(Exception e): target(Point) && call(void setX(int)) { | |||
after() throwing(Exception e): | |||
target(Point) && call(void setX(int)) | |||
{ | |||
System.out.println(e); | |||
} | |||
.... | |||
@@ -691,11 +699,13 @@ join point can be invoked through the special `proceed` call: | |||
[source, java] | |||
.... | |||
void around(Point p, int x): target(p) | |||
&& args(x) | |||
&& call(void setX(int)) { | |||
if (p.assertX(x)) proceed(p, x); | |||
p.releaseResources(); | |||
void around(Point p, int x): | |||
target(p) | |||
&& args(x) | |||
&& call(void setX(int)) | |||
{ | |||
if (p.assertX(x)) proceed(p, x); | |||
p.releaseResources(); | |||
} | |||
.... | |||
@@ -880,7 +890,7 @@ aspect PointAssertions { | |||
.... | |||
[[language-thisJoinPoint]] | |||
=== thisJoinPoint | |||
=== `thisJoinPoint` | |||
AspectJ provides a special reference variable, `thisJoinPoint`, that | |||
contains reflective information about the current join point for the |
@@ -978,8 +978,10 @@ pointcut doesNotThrowMathlike(): | |||
A `ThrowsClausePattern` is a comma-separated list of ``ThrowsClausePatternItem``s, where | |||
`ThrowsClausePatternItem`: :: | |||
`[ ! ] TypeNamePattern` | |||
[source, text] | |||
.... | |||
ThrowsClausePatternItem := [ ! ] TypeNamePattern | |||
.... | |||
A `ThrowsClausePattern` matches the `throws` clause of any code member | |||
signature. To match, each `ThrowsClausePatternItem` must match the |