Browse Source

Finish AsciiDoc improvements in ADK Developer's Notebook (WIP)

Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
tags/V1_9_21_1
Alexander Kriegisch 2 years ago
parent
commit
6450c7d744

+ 13
- 13
docs/adk15ProgGuideDB/adk15notebook.adoc View File

@@ -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]

+ 51
- 62
docs/adk15ProgGuideDB/ataspectj.adoc View File

@@ -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

+ 12
- 13
docs/adk15ProgGuideDB/autoboxing.adoc View File

@@ -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) {
...
// ...
}
....


+ 4
- 4
docs/adk15ProgGuideDB/covariance.adoc View File

@@ -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.

+ 1
- 1
docs/adk15ProgGuideDB/enumeratedtypes.adoc View File

@@ -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

+ 48
- 122
docs/adk15ProgGuideDB/generics.adoc View File

@@ -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:

+ 62
- 57
docs/adk15ProgGuideDB/grammar.adoc View File

@@ -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 ===


+ 2
- 2
docs/adk15ProgGuideDB/ltw.adoc View File

@@ -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.

+ 5
- 3
docs/adk15ProgGuideDB/miscellaneous.adoc View File

@@ -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
- 1
docs/adk15ProgGuideDB/pertypewithin.adoc View File

@@ -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

+ 1
- 1
docs/adk15ProgGuideDB/reflection.adoc View File

@@ -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

+ 14
- 15
docs/adk15ProgGuideDB/varargs.adoc View File

@@ -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`.

+ 81
- 71
docs/progGuideDB/language.adoc View File

@@ -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

+ 4
- 2
docs/progGuideDB/semantics.adoc View File

@@ -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

Loading…
Cancel
Save