aboutsummaryrefslogtreecommitdiffstats
path: root/docs/progGuideDB/semantics.adoc
diff options
context:
space:
mode:
Diffstat (limited to 'docs/progGuideDB/semantics.adoc')
-rw-r--r--docs/progGuideDB/semantics.adoc2176
1 files changed, 0 insertions, 2176 deletions
diff --git a/docs/progGuideDB/semantics.adoc b/docs/progGuideDB/semantics.adoc
deleted file mode 100644
index 0cb513ad0..000000000
--- a/docs/progGuideDB/semantics.adoc
+++ /dev/null
@@ -1,2176 +0,0 @@
-[[semantics]]
-== Language Semantics
-
-[[semantics-intro]]
-=== Introduction
-
-AspectJ extends Java by overlaying a concept of join points onto the
-existing Java semantics and adding a few new program elements to Java:
-
-A join point is a well-defined point in the execution of a program.
-These include method and constructor calls, field accesses and others
-described below.
-
-A pointcut picks out join points, and exposes some of the values in the
-execution context of those join points. There are several primitive
-pointcut designators, and others can be named and defined by the
-`pointcut` declaration.
-
-A piece of advice is code that executes at each join point in a
-pointcut. Advice has access to the values exposed by the pointcut.
-Advice is defined by `before`, `after`, and `around` declarations.
-
-Inter-type declarations form AspectJ's static crosscutting features,
-that is, is code that may change the type structure of a program, by
-adding to or extending interfaces and classes with new fields,
-constructors, or methods. Some inter-type declarations are defined
-through an extension of usual method, field, and constructor
-declarations, and other declarations are made with a new `declare`
-keyword.
-
-An aspect is a crosscutting type that encapsulates pointcuts, advice,
-and static crosscutting features. By type, we mean Java's notion: a
-modular unit of code, with a well-defined interface, about which it is
-possible to do reasoning at compile time. Aspects are defined by the
-`aspect` declaration.
-
-[[semantics-joinPoints]]
-=== Join Points
-
-While aspects define types that crosscut, the AspectJ system does not
-allow completely arbitrary crosscutting. Rather, aspects define types
-that cut across principled points in a program's execution. These
-principled points are called join points.
-
-A join point is a well-defined point in the execution of a program. The
-join points defined by AspectJ are:
-
-Method call::
- When a method is called, not including super calls of non-static
- methods.
-Method execution::
- When the body of code for an actual method executes.
-Constructor call::
- When an object is built and that object's initial constructor is
- called (i.e., not for `super` or `this` constructor calls). The object
- being constructed is returned at a constructor call join point, so its
- return type is considered to be the type of the object, and the object
- itself may be accessed with `after returning` advice.
-Constructor execution::
- When the body of code for an actual constructor executes, after its
- this or super constructor call. The object being constructed is the
- currently executing object, and so may be accessed with the `this()` pointcut.
- The constructor execution join point for a constructor that
- calls a super constructor also includes any non-static initializers of
- enclosing class. No value is returned from a constructor execution
- join point, so its return type is considered to be `void`.
-Static initializer execution::
- When the static initializer for a class executes. No value is returned
- from a static initializer execution join point, so its return type is
- considered to be `void`.
-Object pre-initialization::
- Before the object initialization code for a particular class runs.
- This encompasses the time between the start of its first called
- constructor and the start of its parent's constructor. Thus, the
- execution of these join points encompass the join points of the
- evaluation of the arguments of `this()` and `super()` constructor calls.
- No value is returned from an object pre-initialization join point, so its
- return type is considered to be `void`.
-Object initialization::
- When the object initialization code for a particular class runs. This
- encompasses the time between the return of its parent's constructor
- and the return of its first called constructor. It includes all the
- dynamic initializers and constructors used to create the object. The
- object being constructed is the currently executing object, and so may
- be accessed with the `this()` pointcut. No value is returned from a constructor
- execution join point, so its return type is considered to be `void`.
-Field reference::
- When a non-constant field is referenced. [Note that references to
- constant fields (static final fields bound to a constant string object
- or primitive value) are not join points, since Java requires them to
- be inlined.]
-Field set::
- When a field is assigned to. Field set join points are considered to
- have one argument, the value the field is being set to. No value is
- returned from a field set join point, so its return type is considered
- to be void. [Note that the initializations of constant fields (`static final`
- fields where the initializer is a constant string object or
- primitive value) are not join points, since Java requires their
- references to be inlined.]
-Handler execution::
- When an exception handler executes. Handler execution join points are
- considered to have one argument, the exception being handled. No value
- is returned from a field set join point, so its return type is
- considered to be void.
-Advice execution::
- When the body of code for a piece of advice executes.
-
-Each join point potentially has three pieces of state associated with
-it: the currently executing object, the target object, and an object
-array of arguments. These are exposed by the three state-exposing
-pointcuts, `this`, `target`, and `args`, respectively.
-
-Informally, the currently executing object is the object that a `this`
-expression would pick out at the join point. The target object is where
-control or attention is transferred to by the join point. The arguments
-are those values passed for that transfer of control or attention.
-
-[cols=",,,",options="header",]
-|===
-|*Join Point* |*Current Object* |*Target Object* |*Arguments*
-|Method Call |executing object* |target object** |method arguments
-
-|Method Execution |executing object* |executing object* |method
-arguments
-
-|Constructor Call |executing object* |None |constructor arguments
-
-|Constructor Execution |executing object |executing object |constructor
-arguments
-
-|Static initializer execution |None |None |None
-
-|Object pre-initialization |None |None |constructor arguments
-
-|Object initialization |executing object |executing object |constructor
-arguments
-
-|Field reference |executing object* |target object** |None
-
-|Field assignment |executing object* |target object** |assigned value
-
-|Handler execution |executing object* |executing object* |caught
-exception
-
-|Advice execution |executing aspect |executing aspect |advice arguments
-|===
-
-+++*+++ There is no executing object in static contexts such as static method
-bodies or static initializers.
-
-+++**+++ There is no target object for join points associated with static
-methods or fields.
-
-[[semantics-pointcuts]]
-=== Pointcuts
-
-A pointcut is a program element that picks out join points and exposes
-data from the execution context of those join points. Pointcuts are used
-primarily by advice. They can be composed with boolean operators to
-build up other pointcuts. The primitive pointcuts and combinators
-provided by the language are:
-
-`call(MethodPattern)`::
- Picks out each method call join point whose signature matches `_MethodPattern_`.
-`execution(MethodPattern)`::
- Picks out each method execution join point whose signature matches `_MethodPattern_`.
-`get(FieldPattern)`::
- Picks out each field reference join point whose signature matches `_FieldPattern_`. [Note that references to constant fields (static final fields bound
- to a constant string object or primitive value) are not join points,
- since Java requires them to be inlined.]
-`set(FieldPattern)`::
- Picks out each field set join point whose signature matches `_FieldPattern_`. [Note that the initializations of constant fields (static final
- fields where the initializer is a constant string object or primitive
- value) are not join points, since Java requires their references to be
- inlined.]
-`call(ConstructorPattern)`::
- Picks out each constructor call join point whose signature matches `_ConstructorPattern_`.
-`execution(ConstructorPattern)`::
- Picks out each constructor execution join point whose signature
- matches `_ConstructorPattern_`.
-`initialization(ConstructorPattern)`::
- Picks out each object initialization join point whose signature
- matches `_ConstructorPattern_`.
-`preinitialization(ConstructorPattern)`::
- Picks out each object pre-initialization join point whose signature
- matches `_ConstructorPattern_`.
-`staticinitialization(TypePattern)`::
- Picks out each static initializer execution join point whose signature
- matches `_TypePattern_`.
-`handler(TypePattern)`::
- Picks out each exception handler join point whose signature matches `_TypePattern_`.
-`adviceexecution()`::
- Picks out all advice execution join points.
-`within(TypePattern)`::
- Picks out each join point where the executing code is defined in a
- type matched by `_TypePattern_`.
-`withincode(MethodPattern)`::
- Picks out each join point where the executing code is defined in a
- method whose signature matches `_MethodPattern_`.
-`withincode(ConstructorPattern)`::
- Picks out each join point where the executing code is defined in a
- constructor whose signature matches `_ConstructorPattern_`.
-`cflow(Pointcut)`::
- Picks out each join point in the control flow of any join point `_P_` picked out by `_Pointcut_` , including `_P_` itself.
-`cflowbelow(Pointcut)`::
- Picks out each join point in the control flow of any join point `_P_` picked out by `_Pointcut_`, but not `_P_` itself.
-`this(Type or Id)`::
- Picks out each join point where the currently executing object (the
- object bound to `_this_`) is an instance of `_Type_` , or of the type of the identifier `_Id_` (which must be bound in the enclosing advice or pointcut definition).
- Will not match any join points from static contexts.
-`target(Type or Id)`::
- Picks out each join point where the target object (the object on which
- a call or field operation is applied to) is an instance of `_Type_` , or of the type of the identifier `_Id_` (which must be bound in the enclosing advice or pointcut definition).
- Will not match any calls, gets, or sets of static members.
-`args(Type or Id, ...)`::
- Picks out each join point where the arguments are instances of the
- appropriate type (or type of the identifier if using that form). A `_null_` argument is matched iff the static type of the argument (declared
- parameter type or field type) is the same as, or a subtype of, the
- specified args type.
-`PointcutId(TypePattern or Id, ...)`::
- Picks out each join point that is picked out by the user-defined
- pointcut designator named by `_PointcutId_` .
-`if(BooleanExpression)`::
- Picks out each join point where the boolean expression evaluates to `_true_` . The boolean expression used can only access static members,
- parameters exposed by the enclosing pointcut or advice, and `_thisJoinPoint_` forms. In particular, it cannot call non-static methods on the aspect
- or use return values or exceptions exposed by after advice.
-`! Pointcut`::
- Picks out each join point that is not picked out by `_Pointcut_` .
-`Pointcut0 && Pointcut1`::
- Picks out each join points that is picked out by both `_Pointcut0_` and `_Pointcut1_` .
-`Pointcut0 || Pointcut1`::
- Picks out each join point that is picked out by either pointcuts. `_Pointcut0_` or `_Pointcut1_` .
-`( Pointcut )`::
- Picks out each join points picked out by `_Pointcut_` .
-
-==== Pointcut definition
-
-Pointcuts are defined and named by the programmer with the `pointcut`
-declaration.
-
-[source, java]
-....
-pointcut publicIntCall(int i):
- call(public * *(int)) && args(i);
-....
-
-A named pointcut may be defined in either a class or aspect, and is
-treated as a member of the class or aspect where it is found. As a
-member, it may have an access modifier such as `public` or `private`.
-
-[source, java]
-....
-class C {
- pointcut publicCall(int i):
- call(public * *(int)) && args(i);
-}
-
-class D {
- pointcut myPublicCall(int i):
- C.publicCall(i) && within(SomeType);
-}
-....
-
-Pointcuts that are not final may be declared abstract, and defined
-without a body. Abstract pointcuts may only be declared within abstract
-aspects.
-
-[source, java]
-....
-abstract aspect A {
- abstract pointcut publicCall(int i);
-}
-....
-
-In such a case, an extending aspect may override the abstract pointcut.
-
-[source, java]
-....
-aspect B extends A {
- pointcut publicCall(int i): call(public Foo.m(int)) && args(i);
-}
-....
-
-For completeness, a pointcut with a declaration may be declared `final`.
-
-Though named pointcut declarations appear somewhat like method
-declarations, and can be overridden in subaspects, they cannot be
-overloaded. It is an error for two pointcuts to be named with the same
-name in the same class or aspect declaration.
-
-The scope of a named pointcut is the enclosing class declaration. This
-is different than the scope of other members; the scope of other members
-is the enclosing class _body_. This means that the following code is
-legal:
-
-[source, java]
-....
-aspect B percflow(publicCall()) {
- pointcut publicCall(): call(public Foo.m(int));
-}
-....
-
-==== Context exposure
-
-Pointcuts have an interface; they expose some parts of the execution
-context of the join points they pick out. For example, the PublicIntCall
-above exposes the first argument from the receptions of all public unary
-integer methods. This context is exposed by providing typed formal
-parameters to named pointcuts and advice, like the formal parameters of
-a Java method. These formal parameters are bound by name matching.
-
-On the right-hand side of advice or pointcut declarations, in certain
-pointcut designators, a Java identifier is allowed in place of a type or
-collection of types. The pointcut designators that allow this are
-`this`, `target`, and `args`. In all such cases, using an identifier
-rather than a type does two things. First, it selects join points as
-based on the type of the formal parameter. So the pointcut
-
-[source, java]
-....
-pointcut intArg(int i): args(i);
-....
-
-picks out join points where an `int` (or a `byte`, `short`, or `char`;
-anything assignable to an `int`) is being passed as an argument. Second,
-though, it makes the value of that argument available to the enclosing
-advice or pointcut.
-
-Values can be exposed from named pointcuts as well, so
-
-[source, java]
-....
-pointcut publicCall(int x): call(public *.*(int)) && intArg(x);
-pointcut intArg(int i): args(i);
-....
-
-is a legal way to pick out all calls to public methods accepting an int
-argument, and exposing that argument.
-
-There is one special case for this kind of exposure. Exposing an
-argument of type Object will also match primitive typed arguments, and
-expose a "boxed" version of the primitive. So,
-
-[source, java]
-....
-pointcut publicCall(): call(public *.*(..)) && args(Object);
-....
-
-will pick out all unary methods that take, as their only argument,
-subtypes of Object (i.e., not primitive types like `int`), but
-
-[source, java]
-....
-pointcut publicCall(Object o): call(public *.*(..)) && args(o);
-....
-
-will pick out all unary methods that take any argument: And if the
-argument was an `int`, then the value passed to advice will be of type
-`java.lang.Integer`.
-
-The "boxing" of the primitive value is based on the _original_ primitive
-type. So in the following program
-
-[source, java]
-....
-public class InstanceOf {
- public static void main(String[] args) {
- doInt(5);
- }
-
- static void doInt(int i) { }
-}
-
-aspect IntToLong {
- pointcut el(long l) :
- execution(* doInt(..)) && args(l);
-
- before(Object o) : el(o) {
- System.out.println(o.getClass());
- }
-}
-....
-
-The pointcut will match and expose the integer argument, but it will
-expose it as an `Integer`, not a `Long`.
-
-==== Primitive pointcuts
-
-===== Method-related pointcuts
-
-AspectJ provides two primitive pointcut designators designed to capture
-method call and execution join points.
-
-* `call( MethodPattern )`
-* `execution( MethodPattern )`
-
-===== Field-related pointcuts
-
-AspectJ provides two primitive pointcut designators designed to capture
-field reference and set join points:
-
-* `get( FieldPattern )`
-* `set( FieldPattern )`
-
-All set join points are treated as having one argument, the value the
-field is being set to, so at a set join point, that value can be
-accessed with an `args` pointcut. So an aspect guarding a static integer
-variable x declared in type T might be written as
-
-[source, java]
-....
-aspect GuardedX {
- static final int MAX_CHANGE = 100;
-
- before(int newval): set(static int T.x) && args(newval) {
- if (Math.abs(newval - T.x) > MAX_CHANGE)
- throw new RuntimeException();
- }
-}
-....
-
-===== Object creation-related pointcuts
-
-AspectJ provides primitive pointcut designators designed to capture the
-initializer execution join points of objects.
-
-* `call( ConstructorPattern )`
-* `execution( ConstructorPattern )`
-* `initialization( ConstructorPattern )`
-* `preinitialization( ConstructorPattern )`
-
-===== Class initialization-related pointcuts
-
-AspectJ provides one primitive pointcut designator to pick out static
-initializer execution join points.
-
-* `staticinitialization( TypePattern )`
-
-===== Exception handler execution-related pointcuts
-
-AspectJ provides one primitive pointcut designator to capture execution
-of exception handlers:
-
-* `handler( TypePattern )`
-
-All handler join points are treated as having one argument, the value of
-the exception being handled. That value can be accessed with an `args`
-pointcut. So an aspect used to put `FooException` objects into some
-normal form before they are handled could be written as
-
-[source, java]
-....
-aspect NormalizeFooException {
- before(FooException e): handler(FooException) && args(e) {
- e.normalize();
- }
-}
-....
-
-===== Advice execution-related pointcuts
-
-AspectJ provides one primitive pointcut designator to capture execution
-of advice
-
-* `adviceexecution()`
-
-This can be used, for example, to filter out any join point in the
-control flow of advice from a particular aspect.
-
-[source, java]
-....
-aspect TraceStuff {
- pointcut myAdvice(): adviceexecution() && within(TraceStuff);
-
- before(): call(* *(..)) && !cflow(myAdvice) {
- // do something
- }
-}
-....
-
-===== State-based pointcuts
-
-Many concerns cut across the dynamic times when an object of a
-particular type is executing, being operated on, or being passed around.
-AspectJ provides primitive pointcuts that capture join points at these
-times. These pointcuts use the dynamic types of their objects to pick
-out join points. They may also be used to expose the objects used for
-discrimination.
-
-* `this( Type or Id )`
-* `target( Type or Id )`
-
-The `this` pointcut picks out each join point where the currently
-executing object (the object bound to `this`) is an instance of a
-particular type. The `target` pointcut picks out each join point where
-the target object (the object on which a method is called or a field is
-accessed) is an instance of a particular type. Note that `target` should
-be understood to be the object the current join point is transfering
-control to. This means that the target object is the same as the current
-object at a method execution join point, for example, but may be
-different at a method call join point.
-
-* `args( Type or Id or "..", ...)`
-
-The args pointcut picks out each join point where the arguments are
-instances of some types. Each element in the comma-separated list is one
-of four things. If it is a type name, then the argument in that position
-must be an instance of that type. If it is an identifier, then that
-identifier must be bound in the enclosing advice or pointcut
-declaration, and so the argument in that position must be an instance of
-the type of the identifier (or of any type if the identifier is typed to
-Object). If it is the `*` wildcard, then any argument will match, and if
-it is the special wildcard `..`, then any number of arguments will
-match, just like in signature patterns. So the pointcut
-
-[source, java]
-....
-args(int, .., String)
-....
-
-will pick out all join points where the first argument is an `int` and
-the last is a `String`.
-
-===== Control flow-based pointcuts
-
-Some concerns cut across the control flow of the program. The `cflow`
-and `cflowbelow` primitive pointcut designators capture join points
-based on control flow.
-
-* `cflow( Pointcut )`
-* `cflowbelow( Pointcut )`
-
-The `cflow` pointcut picks out all join points that occur between entry
-and exit of each join point `P` picked out by `Pointcut`, including `P`
-itself. Hence, it picks out the join points _in_ the control flow of the
-join points picked out by `Pointcut`.
-
-The `cflowbelow` pointcut picks out all join points that occur between
-entry and exit of each join point `P` picked out by `Pointcut`, but not
-including `P` itself. Hence, it picks out the join points _below_ the
-control flow of the join points picked out by `Pointcut`.
-
-====== Context exposure from control flows
-
-The `cflow` and `cflowbelow` pointcuts may expose context state through
-enclosed `this`, `target`, and `args` pointcuts.
-
-Anytime such state is accessed, it is accessed through the _most recent_
-control flow that matched. So the "current arg" that would be printed by
-the following program is zero, even though it is in many control flows.
-
-[source, java]
-....
-class Test {
- public static void main(String[] args) {
- fact(5);
- }
- static int fact(int x) {
- if (x == 0) {
- System.err.println("bottoming out");
- return 1;
- }
- else return x * fact(x - 1);
- }
-}
-
-aspect A {
- pointcut entry(int i): call(int fact(int)) && args(i);
- pointcut writing(): call(void println(String)) && ! within(A);
-
- before(int i): writing() && cflow(entry(i)) {
- System.err.println("Current arg is " + i);
- }
-}
-....
-
-It is an error to expose such state through _negated_ control flow
-pointcuts, such as within `!cflowbelow(P)`.
-
-===== Program text-based pointcuts
-
-While many concerns cut across the runtime structure of the program,
-some must deal with the lexical structure. AspectJ allows aspects to
-pick out join points based on where their associated code is defined.
-
-* `within( TypePattern )`
-* `withincode( MethodPattern )`
-* `withincode( ConstructorPattern )`
-
-The `within` pointcut picks out each join point where the code executing
-is defined in the declaration of one of the types in `TypePattern`. This
-includes the class initialization, object initialization, and method and
-constructor execution join points for the type, as well as any join
-points associated with the statements and expressions of the type. It
-also includes any join points that are associated with code in a type's
-nested types, and that type's default constructor, if there is one.
-
-The `withincode` pointcuts picks out each join point where the code
-executing is defined in the declaration of a particular method or
-constructor. This includes the method or constructor execution join
-point as well as any join points associated with the statements and
-expressions of the method or constructor. It also includes any join
-points that are associated with code in a method or constructor's local
-or anonymous types.
-
-===== Expression-based pointcuts
-
-* `if( BooleanExpression )`
-
-The if pointcut picks out join points based on a dynamic property. its
-syntax takes an expression, which must evaluate to a boolean true or
-false. Within this expression, the `thisJoinPoint` object is available.
-So one (extremely inefficient) way of picking out all call join points
-would be to use the pointcut
-
-[source, java]
-....
-if(thisJoinPoint.getKind().equals("call"))
-....
-
-Note that the order of evaluation for pointcut expression components at
-a join point is undefined. Writing `if` pointcuts that have side-effects
-is considered bad style and may also lead to potentially confusing or
-even changing behavior with regard to when or if the test code will run.
-
-==== Signatures
-
-One very important property of a join point is its signature, which is
-used by many of AspectJ's pointcut designators to select particular join
-points.
-
-===== Methods
-
-Join points associated with methods typically have method signatures,
-consisting of a method name, parameter types, return type, the types of
-the declared (checked) exceptions, and some type that the method could
-be called on (below called the "qualifying type").
-
-At a method call join point, the signature is a method signature whose
-qualifying type is the static type used to _access_ the method. This
-means that the signature for the join point created from the call
-`((Integer)i).toString()` is different than that for the call
-`((Object)i).toString()`, even if `i` is the same variable.
-
-At a method execution join point, the signature is a method signature
-whose qualifying type is the declaring type of the method.
-
-===== Fields
-
-Join points associated with fields typically have field signatures,
-consisting of a field name and a field type. A field reference join
-point has such a signature, and no parameters. A field set join point
-has such a signature, but has a has a single parameter whose type is the
-same as the field type.
-
-===== Constructors
-
-Join points associated with constructors typically have constructor
-signatures, consisting of a parameter types, the types of the declared
-(checked) exceptions, and the declaring type.
-
-At a constructor call join point, the signature is the constructor
-signature of the called constructor. At a constructor execution join
-point, the signature is the constructor signature of the currently
-executing constructor.
-
-At object initialization and pre-initialization join points, the
-signature is the constructor signature for the constructor that started
-this initialization: the first constructor entered during this type's
-initialization of this object.
-
-===== Others
-
-At a handler execution join point, the signature is composed of the
-exception type that the handler handles.
-
-At an advice execution join point, the signature is composed of the
-aspect type, the parameter types of the advice, the return type (void
-for all but around advice) and the types of the declared (checked)
-exceptions.
-
-==== Matching
-
-The `withincode`, `call`, `execution`, `get`, and `set` primitive
-pointcut designators all use signature patterns to determine the join
-points they describe. A signature pattern is an abstract description of
-one or more join-point signatures. Signature patterns are intended to
-match very closely the same kind of things one would write when
-declaring individual members and constructors.
-
-Method declarations in Java include method names, method parameters,
-return types, modifiers like static or private, and throws clauses,
-while constructor declarations omit the return type and replace the
-method name with the class name. The start of a particular method
-declaration, in class `Test`, for example, might be
-
-[source, java]
-....
-class C {
- public final void foo() throws ArrayOutOfBoundsException { ... }
-}
-....
-
-In AspectJ, method signature patterns have all these, but most elements
-can be replaced by wildcards. So
-
-[source, java]
-....
-call(public final void C.foo() throws ArrayOutOfBoundsException)
-....
-
-picks out call join points to that method, and the pointcut
-
-[source, java]
-....
-call(public final void *.*() throws ArrayOutOfBoundsException)
-....
-
-picks out all call join points to methods, regardless of their name name
-or which class they are defined on, so long as they take no arguments,
-return no value, are both `public` and `final`, and are declared to
-throw ``ArrayOutOfBoundsException``s.
-
-The defining type name, if not present, defaults to *, so another way of
-writing that pointcut would be
-
-[source, java]
-....
-call(public final void *() throws ArrayOutOfBoundsException)
-....
-
-The wildcard `..` indicates zero or more parameters, so
-
-[source, java]
-....
-execution(void m(..))
-....
-
-picks out execution join points for void methods named `m`, of any
-number of arguments, while
-
-[source, java]
-....
-execution(void m(.., int))
-....
-
-picks out execution join points for void methods named `m` whose last
-parameter is of type `int`.
-
-The modifiers also form part of the signature pattern. If an AspectJ
-signature pattern should match methods without a particular modifier,
-such as all non-public methods, the appropriate modifier should be
-negated with the `!` operator. So,
-
-[source, java]
-....
-withincode(!public void foo())
-....
-
-picks out all join points associated with code in null non-public void
-methods named `foo`, while
-
-[source, java]
-....
-withincode(void foo())
-....
-
-picks out all join points associated with code in null void methods
-named `foo`, regardless of access modifier.
-
-Method names may contain the * wildcard, indicating any number of
-characters in the method name. So
-
-[source, java]
-....
-call(int *())
-....
-
-picks out all call join points to `int` methods regardless of name, but
-
-[source, java]
-....
-call(int get*())
-....
-
-picks out all call join points to `int` methods where the method name
-starts with the characters "get".
-
-AspectJ uses the `new` keyword for constructor signature patterns rather
-than using a particular class name. So the execution join points of
-private null constructor of a class `C` defined to throw an
-`ArithmeticException` can be picked out with
-
-[source, java]
-....
-execution(private C.new() throws ArithmeticException)
-....
-
-===== Matching based on the declaring type
-
-The signature-matching pointcuts all specify a declaring type, but the
-meaning varies slightly for each join point signature, in line with Java
-semantics.
-
-When matching for pointcuts `withincode`, `get`, and `set`, the
-declaring type is the class that contains the declaration.
-
-When matching method-call join points, the declaring type is the static
-type used to access the method. A common mistake is to specify a
-declaring type for the `call` pointcut that is a subtype of the
-originally-declaring type. For example, given the class
-
-[source, java]
-....
-class Service implements Runnable {
- public void run() { ... }
-}
-....
-
-the following pointcut
-
-[source, java]
-....
-call(void Service.run())
-....
-
-would fail to pick out the join point for the code
-
-[source, java]
-....
-((Runnable) new Service()).run();
-....
-
-Specifying the originally-declaring type is correct, but would pick out
-any such call (here, calls to the `run()` method of any `Runnable`). In
-this situation, consider instead picking out the target type:
-
-[source, java]
-....
-call(void run()) && target(Service)
-....
-
-When matching method-execution join points, if the execution pointcut
-method signature specifies a declaring type, the pointcut will only
-match methods declared in that type, or methods that override methods
-declared in or inherited by that type. So the pointcut
-
-[source, java]
-....
-execution(public void Middle.*())
-....
-
-picks out all method executions for public methods returning void and
-having no arguments that are either declared in, or inherited by,
-`Middle`, even if those methods are overridden in a subclass of `Middle`. So
-the pointcut would pick out the method-execution join point for `Sub.m()`
-in this code:
-
-[source, java]
-....
-class Super {
- protected void m() { /*...*/ }
-}
-
-class Middle extends Super {}
-
-class Sub extends Middle {
- public void m() { /*...*/ }
-}
-....
-
-===== Matching based on the `throws` clause
-
-Type patterns may be used to pick out methods and constructors based on
-their `throws` clauses. This allows the following two kinds of extremely
-wildcarded pointcuts:
-
-[source, java]
-....
-pointcut throwsMathlike():
- // each call to a method with a throws clause containing at least
- // one exception exception with "Math" in its name.
- call(* *(..) throws *..*Math*);
-
-pointcut doesNotThrowMathlike():
- // each call to a method with a throws clause containing no
- // exceptions with "Math" in its name.
- call(* *(..) throws !*..*Math*);
-....
-
-A `ThrowsClausePattern` is a comma-separated list of ``ThrowsClausePatternItem``s, where
-
-[source, text]
-....
-ThrowsClausePatternItem := [ ! ] TypeNamePattern
-....
-
-A `ThrowsClausePattern` matches the `throws` clause of any code member
-signature. To match, each `ThrowsClausePatternItem` must match the
-`throws` clause of the member in question. If any item doesn't match, then
-the whole pattern doesn't match.
-
-If a `ThrowsClausePatternItem` begins with `!`, then it matches a
-particular `throws` clause if and only if _none_ of the types named in the
-`throws` clause is matched by the `TypeNamePattern`.
-
-If a `ThrowsClausePatternItem` does not begin with `!`, then it matches
-a throws clause if and only if _any_ of the types named in the `throws`
-clause is matched by the `TypeNamePattern`.
-
-The rule for `!` matching has one potentially surprising property, in
-that these two pointcuts
-
-. `call(* *(..) throws !IOException)`
-. `call(* *(..) throws (!IOException))`
-
-will match differently on calls to
-
-[source, java]
-....
-void m() throws RuntimeException, IOException {}
-....
-
-[1] will *not* match the method `m()`, because ``m``'s throws clause
-declares that it `throws IOException`.
-
-[2] *will* match the method `m()`, because ``m``'s throws clause declares that
-it throws some exception which does not match `IOException`, i.e. `RuntimeException`.
-
-==== Type patterns
-
-Type patterns are a way to pick out collections of types and use them in
-places where you would otherwise use only one type. The rules for using
-type patterns are simple.
-
-===== Exact type pattern
-
-First, all type names are also type patterns. So `Object`,
-`java.util.HashMap`, `Map.Entry`, `int` are all type patterns.
-
-If a type pattern is an exact type - if it doesn't include a wildcard -
-then the matching works just like normal type lookup in Java:
-
-* Patterns that have the same names as primitive types (like `int`) match those
- primitive types.
-* Patterns that are qualified by package names (like `java.util.HashMap`) match
- types in other packages.
-* Patterns that are not qualified (like `HashMap`) match types that are resolved
- by Java's normal scope rules. So, for example, `HashMap` might match a package-level
- type in the same package or a type that have been imported with Java's `import`
- form. But it would not match `java.util.HashMap` unless the aspect were in `java.util`
- or the type had been imported.
-
-So exact type patterns match based on usual Java scope rules.
-
-===== Type name patterns
-
-There is a special type name, `\*`, which is also a type pattern. `*` picks
-out all types, including primitive types. So
-
-[source, java]
-....
-call(void foo(*))
-....
-
-picks out all call join points to void methods named foo, taking one
-argument of any type.
-
-Type names that contain the two wildcards `\*` and `..` are also type
-patterns. The `*` wildcard matches zero or more characters characters
-except for `.`, so it can be used when types have a certain naming
-convention. So
-
-[source, java]
-....
-handler(java.util.*Map)
-....
-
-picks out the types `java.util.Map` and `java.util.java.util.HashMap`, among
-others, and
-
-[source, java]
-....
-handler(java.util.*)
-....
-
-picks out all types that start with `java.util.` and don't have any
-more ``.``s, that is, the types in the `java.util` package, but not inner
-types (such as `java.util.Map.Entry`).
-
-The `..` wildcard matches any sequence of characters that start and
-end with a `.`, so it can be used to pick out all types in any
-subpackage, or all inner types. So
-
-[source, java]
-....
-within(com.xerox..*)
-....
-
-picks out all join points where the code is in any declaration of a type
-whose name begins with `com.xerox.`.
-
-Type patterns with wildcards do not depend on Java's usual scope rules -
-they match against all types available to the weaver, not just those
-that are imported into an Aspect's declaring file.
-
-===== Subtype patterns
-
-It is possible to pick out all subtypes of a type (or a collection of
-types) with the `+` wildcard. The `+` wildcard follows immediately a
-type name pattern. So, while
-
-[source, java]
-....
-call(Foo.new())
-....
-
-picks out all constructor call join points where an instance of exactly
-type `Foo` is constructed,
-
-[source, java]
-....
-call(Foo+.new())
-....
-
-picks out all constructor call join points where an instance of any
-subtype of `Foo` (including `Foo` itself) is constructed, and the unlikely
-
-[source, java]
-....
-call(*Handler+.new())
-....
-
-picks out all constructor call join points where an instance of any
-subtype of any type whose name ends in `Handler` is constructed.
-
-===== Array type patterns
-
-A type name pattern or subtype pattern can be followed by one or more
-sets of square brackets to make array type patterns. So `Object[]` is an
-array type pattern, and so is `com.xerox..*[][]`, and so is `Object+[]`.
-
-===== Type patterns
-
-Type patterns are built up out of type name patterns, subtype patterns,
-and array type patterns, and constructed with boolean operators `&&`,
-`||`, and `!`. So
-
-[source, java]
-....
-staticinitialization(Foo || Bar)
-....
-
-picks out the static initializer execution join points of either `Foo` or
-`Bar`, and
-
-[source, java]
-....
-call((Foo+ && ! Foo).new(..))
-....
-
-picks out the constructor call join points when a subtype of `Foo`, but
-not `Foo` itself, is constructed.
-
-==== Pattern Summary
-
-Here is a summary of the pattern syntax used in AspectJ:
-
-[source, text]
-....
-MethodPattern =
- [ModifiersPattern] TypePattern
- [TypePattern . ] IdPattern (TypePattern | ".." , ... )
- [ throws ThrowsPattern ]
-ConstructorPattern =
- [ModifiersPattern ]
- [TypePattern . ] new (TypePattern | ".." , ...)
- [ throws ThrowsPattern ]
-FieldPattern =
- [ModifiersPattern] TypePattern [TypePattern . ] IdPattern
-ThrowsPattern =
- [ ! ] TypePattern , ...
-TypePattern =
- IdPattern [ + ] [ [] ... ]
- | ! TypePattern
- | TypePattern && TypePattern
- | TypePattern || TypePattern
- | ( TypePattern )
-IdPattern =
- Sequence of characters, possibly with special * and .. wildcards
-ModifiersPattern =
- [ ! ] JavaModifier ...
-....
-
-[[semantics-advice]]
-=== Advice
-
-Each piece of advice is of the form
-
-[source, text]
-....
-[ strictfp ] AdviceSpec [ throws TypeList ] : Pointcut { Body }
-....
-
-where `AdviceSpec` is one of
-
-* `before( Formals )`
-* `after( Formals ) returning [ ( Formal ) ]`
-* `after( Formals ) throwing [ ( Formal ) ]`
-* `after( Formals )`
-* `Type around( Formals )`
-
-and where `Formal` refers to a variable binding like those used for
-method parameters, of the form `Type` `Variable-Name`, and `Formals`
-refers to a comma-delimited list of `Formal`.
-
-Advice defines crosscutting behavior. It is defined in terms of
-pointcuts. The code of a piece of advice runs at every join point picked
-out by its pointcut. Exactly how the code runs depends on the kind of
-advice.
-
-AspectJ supports three kinds of advice. The kind of advice determines
-how it interacts with the join points it is defined over. Thus AspectJ
-divides advice into that which runs *before* its join points, that which
-runs *after* its join points, and that which runs *in place of (or
-"around")* its join points.
-
-While `before` advice is relatively unproblematic, there can be three
-interpretations of `after` advice: After the execution of a join point
-completes normally, after it throws an exception, or after it does
-either one. AspectJ allows `after` advice for any of these situations:
-
-[source, java]
-....
-aspect A {
- pointcut publicCall(): call(public Object *(..));
-
- after() returning (Object o): publicCall() {
- System.out.println("Returned normally with " + o);
- }
-
- after() throwing (Exception e): publicCall() {
- System.out.println("Threw an exception: " + e);
- }
-
- after(): publicCall(){
- System.out.println("Returned or threw an Exception");
- }
-}
-....
-
-`after returning` advice may not care about its returned object, in which
-case it may be written
-
-[source, java]
-....
-after() returning: call(public Object *(..)) {
- System.out.println("Returned normally");
-}
-....
-
-If `after returning` does expose its returned object, then the type of the
-parameter is considered to be an `instanceof`-like constraint on the
-advice: it will run only when the return value is of the appropriate
-type.
-
-A value is of the appropriate type if it would be assignable to a
-variable of that type, in the Java sense. That is, a `byte` value is
-assignable to a `short` parameter but not vice-versa, an `int` is
-assignable to a `float` parameter, `boolean` values are only assignable
-to `boolean` parameters, and reference types work by `instanceof`.
-
-There are two special cases: If the exposed value is typed to `Object`,
-then the advice is not constrained by that type: the actual return value
-is converted to an object type for the body of the advice: `int` values
-are represented as `java.lang.Integer` objects, etc, and no value (from
-`void` methods, for example) is represented as `null`.
-
-Secondly, the `null` value is assignable to a parameter `T` if the join
-point _could_ return something of type `T`.
-
-`around` advice runs in place of the join point it operates over, rather
-than before or after it. Because `around` is allowed to return a value, it
-must be declared with a return type, like a method.
-
-Thus, a simple use of `around` advice is to make a particular method
-constant:
-
-[source, java]
-....
-aspect A {
- int around(): call(int C.foo()) {
- return 3;
- }
-}
-....
-
-Within the body of `around` advice, though, the computation of the
-original join point can be executed with the special syntax
-
-[source, java]
-....
-proceed( ... )
-....
-
-The `proceed` form takes as arguments the context exposed by the around's
-pointcut, and returns whatever the around is declared to return. So the
-following around advice will double the second argument to `foo`
-whenever it is called, and then halve its result:
-
-[source, java]
-....
-aspect A {
- int around(int i): call(int C.foo(Object, int)) && args(i) {
- int newi = proceed(i*2)
- return newi/2;
- }
-}
-....
-
-If the return value of `around` advice is typed to `Object`, then the
-result of proceed is converted to an object representation, even if it
-is originally a primitive value. And when the advice returns an `Object`
-value, that value is converted back to whatever representation it was
-originally. So another way to write the doubling and halving advice is:
-
-[source, java]
-....
-aspect A {
- Object around(int i): call(int C.foo(Object, int)) && args(i) {
- Integer newi = (Integer) proceed(i*2)
- return new Integer(newi.intValue() / 2);
- }
-}
-....
-
-Any occurence of `proceed(..)` within the body of around advice is
-treated as the special `proceed` form (even if the aspect defines a method
-named `proceed`), unless a target other than the aspect instance is
-specified as the recipient of the call. For example, in the following
-program the first call to `proceed` will be treated as a method call to
-the `ICanProceed` instance, whereas the second call to `proceed` is
-treated as the special `proceed` form.
-
-[source, java]
-....
-aspect A {
- Object around(ICanProceed canProceed) : execution(* *(..)) && this(canProceed) {
- canProceed.proceed(); // a method call
- return proceed(canProceed); // the special proceed form
- }
-
- private Object proceed(ICanProceed canProceed) {
- // this method cannot be called from inside the body of around advice
- // in the aspect
- }
-}
-....
-
-In all kinds of advice, the parameters of the advice behave exactly like
-method parameters. In particular, assigning to any parameter affects
-only the value of the parameter, not the value that it came from. This
-means that
-
-[source, java]
-....
-aspect A {
- after() returning (int i): call(int C.foo()) {
- i = i * 2;
- }
-}
-....
-
-will _not_ double the returned value of the advice. Rather, it will
-double the local parameter. Changing the values of parameters or return
-values of join points can be done by using `around` advice.
-
-With `proceed(..)` it is possible to change the values used by
-less-precedent advice and the underlying join point by supplying
-different values for the variables. For example, this aspect replaces
-the string bound to `s` in the named pointcut `privateData`:
-
-[source, java]
-....
-aspect A {
- Object around(String s): MyPointcuts.privateData(s) {
- return proceed("private data");
- }
-}
-....
-
-If you replace an argument to `proceed(..)`, you can cause a
-`ClassCastException` at runtime when the argument refers to a supertype
-of the actual type and you do not supply a reference of the actual type.
-In the following aspect, the around advice replaces the declared target
-`List` with an `ArrayList`. This is valid code at compile-time since the
-types match.
-
-[source, java]
-....
-import java.util.*;
-
-aspect A {
- Object around(List list): call(* List+.*()) && target(list) {
- return proceed(new ArrayList());
- }
-}
-....
-
-But imagine a simple program where the actual target is `LinkedList`. In
-this case, the advice would cause a `ClassCastException` at runtime, and
-`peek()` is not declared in `ArrayList`.
-
-[source, java]
-....
-public class Test {
- public static void main(String[] args) {
- new LinkedList().peek();
- }
-}
-....
-
-The `ClassCastException` can occur even in situations where it appears
-to be unnecessary, e.g., if the program is changed to call `size()`,
-declared in `List`:
-
-[source, java]
-....
-public class Test {
- public static void main(String[] args) {
- new LinkedList().size();
- }
-}
-....
-
-There will still be a `ClassCastException` because it is impossible to
-prove that there won't be a runtime binary-compatible change in the
-hierarchy of `LinkedList` or some other advice on the join point that
-requires a `LinkedList`.
-
-==== Advice modifiers
-
-The `strictfp` modifier is the only modifier allowed on advice, and it
-has the effect of making all floating-point expressions within the
-advice be FP-strict.
-
-==== Advice and checked exceptions
-
-An advice declaration must include a `throws` clause listing the checked
-exceptions the body may throw. This list of checked exceptions must be
-compatible with each target join point of the advice, or an error is
-signalled by the compiler.
-
-For example, in the following declarations:
-
-[source, java]
-....
-import java.io.FileNotFoundException;
-
-class C {
- int i;
- int getI() { return i; }
-}
-
-aspect A {
- before(): get(int C.i) {
- throw new FileNotFoundException();
- }
-
- before() throws FileNotFoundException: get(int C.i) {
- throw new FileNotFoundException();
- }
-}
-....
-
-both pieces of advice are illegal. The first because the body throws an
-undeclared checked exception, and the second because field get join
-points cannot throw ``FileNotFoundException``s.
-
-The exceptions that each kind of join point in AspectJ may throw are:
-
-method call and execution::
- the checked exceptions declared by the target method's `throws` clause.
-constructor call and execution::
- the checked exceptions declared by the target constructor's `throws` clause.
-field get and set::
- no checked exceptions can be thrown from these join points.
-exception handler execution::
- the exceptions that can be thrown by the target exception handler.
-static initializer execution::
- no checked exceptions can be thrown from these join points.
-pre-initialization and initialization::
- any exception that is in the `throws` clause of all constructors of the initialized class.
-advice execution::
- any exception that is in the `throws` clause of the advice.
-
-==== Advice precedence
-
-Multiple pieces of advice may apply to the same join point. In such
-cases, the resolution order of the advice is based on advice precedence.
-
-===== Determining precedence
-
-There are a number of rules that determine whether a particular piece of
-advice has precedence over another when they advise the same join point.
-
-If the two pieces of advice are defined in different aspects, then there
-are three cases:
-
-* If aspect `A` is matched earlier than aspect `B` in some `declare precedence`
- form, then all advice in concrete aspect `A` has precedence over all
- advice in concrete aspect `B` when they are on the same join point.
-* Otherwise, if aspect `A` is a subaspect of aspect `B`, then all advice
- defined in `A` has precedence over all advice defined in `B`. So, unless
- otherwise specified with `declare precedence`, advice in a subaspect has
- precedence over advice in a superaspect.
-* Otherwise, if two pieces of advice are defined in two different
- aspects, it is undefined which one has precedence.
-
-If the two pieces of advice are defined in the same aspect, then there
-are two cases:
-
-* If either are `after` advice, then the one that appears later in the aspect has precedence
- over the one that appears earlier.
-* Otherwise, then the one that appears earlier in the aspect has
- precedence over the one that appears later.
-
-These rules can lead to circularity, such as
-
-[source, java]
-....
-aspect A {
- before(): execution(void main(String[] args)) {}
- after(): execution(void main(String[] args)) {}
- before(): execution(void main(String[] args)) {}
-}
-....
-
-such circularities will result in errors signalled by the compiler.
-
-===== Effects of precedence
-
-At a particular join point, advice is ordered by precedence.
-
-A piece of `around` advice controls whether advice of lower precedence
-will run by calling `proceed`. The call to `proceed` will run the advice
-with next precedence, or the computation under the join point if there
-is no further advice.
-
-A piece of `before` advice can prevent advice of lower precedence from
-running by throwing an exception. If it returns normally, however, then
-the advice of the next precedence, or the computation under the join
-pint if there is no further advice, will run.
-
-Running `after returning` advice will run the advice of next precedence,
-or the computation under the join point if there is no further advice.
-Then, if that computation returned normally, the body of the advice will
-run.
-
-Running `after throwing` advice will run the advice of next precedence,
-or the computation under the join point if there is no further advice.
-Then, if that computation threw an exception of an appropriate type, the
-body of the advice will run.
-
-Running `after` advice will run the advice of next precedence, or the
-computation under the join point if there is no further advice. Then the
-body of the advice will run.
-
-==== Reflective access to the join point
-
-Three special variables are visible within bodies of advice and within
-`if()` pointcut expressions: `thisJoinPoint`, `thisJoinPointStaticPart`,
-and `thisEnclosingJoinPointStaticPart`. Each is bound to an object that
-encapsulates some of the context of the advice's current or enclosing
-join point. These variables exist because some pointcuts may pick out
-very large collections of join points. For example, the pointcut
-
-[source, java]
-....
-pointcut publicCall(): call(public * *(..));
-....
-
-picks out calls to many methods. Yet the body of advice over this
-pointcut may wish to have access to the method name or parameters of a
-particular join point.
-
-* `thisJoinPoint` is bound to a complete join point object.
-
-* `thisJoinPointStaticPart` is bound to a part of the join point object
- that includes less information, but for which no memory allocation is
- required on each execution of the advice. It is equivalent to
- `thisJoinPoint.getStaticPart()`.
-
-* `thisEnclosingJoinPointStaticPart` is bound to the static part of the
- join point enclosing the current join point. Only the static part of
- this enclosing join point is available through this mechanism.
-
-Standard Java reflection uses objects from the `java.lang.reflect`
-hierarchy to build up its reflective objects. Similarly, AspectJ join
-point objects have types in a type hierarchy. The type of objects bound
-to `thisJoinPoint` is `org.aspectj.lang.JoinPoint`, while
-`thisStaticJoinPoint` is bound to objects of interface type
-`org.aspectj.lang.JoinPoint.StaticPart`.
-
-[[semantics-declare]]
-=== Static crosscutting
-
-Advice declarations change the behavior of classes they crosscut, but do
-not change their static type structure. For crosscutting concerns that
-do operate over the static structure of type hierarchies, AspectJ
-provides inter-type member declarations and other `declare` forms.
-
-==== Inter-type member declarations
-
-AspectJ allows the declaration of members by aspects that are associated
-with other types.
-
-An inter-type method declaration looks like
-
-* `[ Modifiers ] Type OnType . Id ( Formals ) [ ThrowsClause ] { Body }`
-* `abstract [ Modifiers ] Type OnType . Id ( Formals ) [ ThrowsClause ] ;`
-
-The effect of such a declaration is to make `OnType` support the new
-method. Even if `OnType` is an interface. Even if the method is neither
-public nor abstract. So the following is legal AspectJ code:
-
-[source, java]
-....
-interface Iface {}
-
-aspect A {
- private void Iface.m() {
- System.err.println("I'm a private method on an interface");
- }
-
- void worksOnI(Iface iface) {
- // calling a private method on an interface
- iface.m();
- }
-}
-....
-
-An inter-type constructor declaration looks like
-
-* `[ Modifiers ] OnType . new ( Formals ) [ ThrowsClause ] { Body }`
-
-The effect of such a declaration is to make `OnType` support the new
-constructor. It is an error for `OnType` to be an interface.
-
-Inter-type declared constructors cannot be used to assign a value to a
-final variable declared in `OnType`. This limitation significantly
-increases the ability to both understand and compile the `OnType` class
-and the declaring aspect separately.
-
-Note that in the Java language, classes that define no constructors have
-an implicit no-argument constructor that just calls `super()`. This
-means that attempting to declare a no-argument inter-type constructor on
-such a class may result in a conflict, even though it _looks_ like no
-constructor is defined.
-
-An inter-type field declaration looks like one of
-
-* `[ Modifiers ] Type OnType . Id = Expression ;`
-* `[ Modifiers ] Type OnType . Id ;`
-
-The effect of such a declaration is to make `OnType` support the new
-field. Even if `OnType` is an interface. Even if the field is neither
-public, nor static, nor final.
-
-The initializer, if any, of an inter-type field declaration runs before
-the class-local initializers defined in its target class.
-
-Any occurrence of the identifier `this` in the body of an inter-type
-constructor or method declaration, or in the initializer of an
-inter-type field declaration, refers to the `OnType` object rather than
-to the aspect type; it is an error to access `this` in such a position
-from a `static` inter-type member declaration.
-
-==== Access modifiers
-
-Inter-type member declarations may be `public` or `private`, or have default
-(package-protected) visibility. AspectJ does not provide protected
-inter-type members.
-
-The access modifier applies in relation to the aspect, not in relation
-to the target type. So a private inter-type member is visible only from
-code that is defined within the declaring aspect. A default-visibility
-inter-type member is visible only from code that is defined within the
-declaring aspect's package.
-
-Note that a declaring a private inter-type method (which AspectJ
-supports) is very different from inserting a private method declaration
-into another class. The former allows access only from the declaring
-aspect, while the latter would allow access only from the target type.
-Java serialization, for example, uses the presense of a private method
-`void writeObject(ObjectOutputStream)` for the implementation of
-`java.io.Serializable`. A private inter-type declaration of that method
-would not fulfill this requirement, since it would be private to the
-aspect, not private to the target type.
-
-The access modifier of abstract inter-type methods has one constraint:
-It is illegal to declare an abstract non-public inter-type method on a
-public interface. This is illegal because it would say that a public
-interface has a constraint that only non-public implementors must
-fulfill. This would not be compatible with Java's type system.
-
-==== Conflicts
-
-Inter-type declarations raise the possibility of conflicts among locally
-declared members and inter-type members. For example, assuming
-`otherPackage` is not the package containing the aspect `A`, the code
-
-[source, java]
-....
-aspect A {
- private Registry otherPackage.onType.r;
-
- public void otherPackage.onType.register(Registry r) {
- r.register(this);
- this.r = r;
- }
-}
-....
-
-declares that `onType` in `otherPackage` has a field `r`. This field,
-however, is only accessible from the code inside of aspect `A`. The
-aspect also declares that `onType` has a method "`register`", but makes
-this method accessible from everywhere.
-
-If `onType` already defines a private or package-protected field `r`,
-there is no conflict: The aspect cannot see such a field, and no code in
-`otherPackage` can see the inter-type `r`.
-
-If `onType` defines a public field `r`, there is a conflict: The
-expression
-
-[source, java]
-....
-this.r = r
-....
-
-is an error, since it is ambiguous whether the private inter-type `r`
-or the public locally-defined `r` should be used.
-
-If `onType` defines a method `register(Registry)` there is a conflict,
-since it would be ambiguous to any code that could see such a defined
-method which `register(Registry)` method was applicable.
-
-Conflicts are resolved as much as possible as per Java's conflict
-resolution rules:
-
-* A subclass can inherit multiple fields from its superclasses, all with the
- same name and type. However, it is an error to have an ambiguous reference
- to a field.
-* A subclass can only inherit multiple methods with the same name and argument
- types from its superclasses if only zero or one of them is concrete (i.e., all
- but one is abstract, or all are abstract).
-
-Given a potential conflict between inter-type member declarations in
-different aspects, if one aspect has precedence over the other its
-declaration will take effect without any conflict notice from compiler.
-This is true both when the precedence is declared explicitly with
-`declare precedence` as well as when when sub-aspects implicitly have
-precedence over their super-aspect.
-
-==== Extension and Implementation
-
-An aspect may change the inheritance hierarchy of a system by changing
-the superclass of a type or adding a superinterface onto a type, with
-the `declare parents` form.
-
-* `declare parents: TypePattern extends Type ;`
-* `declare parents: TypePattern implements TypeList ;`
-
-For example, if an aspect wished to make a particular class runnable, it
-might define appropriate inter-type `void
- run()` method, but it should also declare that the class
-fulfills the `Runnable` interface. In order to implement the methods in
-the `Runnable` interface, the inter-type `run()` method must be public:
-
-[source, java]
-....
-aspect A {
- declare parents: SomeClass implements Runnable;
-
- public void SomeClass.run() { ... }
-}
-....
-
-==== Interfaces with members
-
-Through the use of inter-type members, interfaces may now carry
-(non-public-static-final) fields and (non-public-abstract) methods that
-classes can inherit. Conflicts may occur from ambiguously inheriting
-members from a superclass and multiple superinterfaces.
-
-Because interfaces may carry non-static initializers, each interface
-behaves as if it has a zero-argument constructor containing its
-initializers. The order of super-interface instantiation is observable.
-We fix this order with the following properties: A supertype is
-initialized before a subtype, initialized code runs only once, and the
-initializers for a type's superclass are run before the initializers for
-its superinterfaces. Consider the following hierarchy where {`Object`,
-`C`, `D`, `E`} are classes, {`M`, `N`, `O`, `P`, `Q`} are interfaces.
-
-[source, text]
-....
-Object M O
- \ / \ /
- C N Q
- \ / /
- D P
- \ /
- E
-....
-
-when a new `E` is instantiated, the initializers run in this order:
-
-[source, text]
-....
-Object M C O N D Q P E
-....
-
-==== Warnings and Errors
-
-An aspect may specify that a particular join point should never be
-reached.
-
-* `declare error: Pointcut : String ;`
-* `declare warning: Pointcut : String ;`
-
-If the compiler determines that a join point in `Pointcut` could
-possibly be reached, then it will signal either an error or warning, as
-declared, using the `String` for its message.
-
-==== Softened exceptions
-
-An aspect may specify that a particular kind of exception, if thrown at
-a join point, should bypass Java's usual static exception checking
-system and instead be thrown as a `org.aspectj.lang.SoftException`,
-which is subtype of `RuntimeException` and thus does not need to be
-declared.
-
-* `declare soft: Type : Pointcut ;`
-
-For example, the aspect
-
-[source, java]
-....
-aspect A {
- declare soft: Exception: execution(void main(String[] args));
-}
-....
-
-Would, at the execution join point, catch any `Exception` and rethrow a
-`org.aspectj.lang.SoftException` containing original exception.
-
-This is similar to what the following advice would do
-
-[source, java]
-....
-aspect A {
- void around() execution(void main(String[] args)) {
- try { proceed(); }
- catch (Exception e) {
- throw new org.aspectj.lang.SoftException(e);
- }
- }
-}
-....
-
-except, in addition to wrapping the exception, it also affects Java's
-static exception checking mechanism.
-
-Like advice, the declare soft form has no effect in an abstract aspect
-that is not extended by a concreate aspect. So the following code will
-not compile unless it is compiled with an extending concrete aspect:
-
-[source, java]
-....
-abstract aspect A {
- abstract pointcut softeningPC();
-
- before() : softeningPC() {
- Class.forName("FooClass"); // error: uncaught ClassNotFoundException
- }
-
- declare soft : ClassNotFoundException : call(* Class.*(..));
-}
-....
-
-[[advice-precedence-cross]]
-==== Advice Precedence
-
-An aspect may declare a precedence relationship between concrete aspects
-with the `declare precedence` form:
-
-* `declare precedence : TypePatternList ;`
-
-This signifies that if any join point has advice from two concrete
-aspects matched by some pattern in `TypePatternList`, then the
-precedence of the advice will be the order of in the list.
-
-In `TypePatternList`, the wildcard `*` can appear at most once, and it
-means "any type not matched by any other pattern in the list".
-
-For example, the constraints that (1) aspects that have Security as part
-of their name should have precedence over all other aspects, and (2) the
-Logging aspect (and any aspect that extends it) should have precedence
-over all non-security aspects, can be expressed by:
-
-[source, java]
-....
-declare precedence: *..*Security*, Logging+, *;
-....
-
-For another example, the `CountEntry` aspect might want to count the entry
-to methods in the current package accepting a Type object as its first
-argument. However, it should count all entries, even those that the
-aspect `DisallowNulls` causes to throw exceptions. This can be
-accomplished by stating that `CountEntry` has precedence over
-`DisallowNulls`. This declaration could be in either aspect, or in
-another, ordering aspect:
-
-[source, java]
-....
-aspect Ordering {
- declare precedence: CountEntry, DisallowNulls;
-}
-
-aspect DisallowNulls {
- pointcut allTypeMethods(Type obj): call(* *(..)) && args(obj, ..);
- before(Type obj): allTypeMethods(obj) {
- if (obj == null) throw new RuntimeException();
- }
-}
-
-aspect CountEntry {
- pointcut allTypeMethods(Type obj): call(* *(..)) && args(obj, ..);
- static int count = 0;
- before(): allTypeMethods(Type) {
- count++;
- }
-}
-....
-
-===== Various cycles
-
-It is an error for any aspect to be matched by more than one TypePattern
-in a single decare precedence, so:
-
-[source, java]
-....
-declare precedence: A, B, A ; // error
-....
-
-However, multiple declare precedence forms may legally have this kind of
-circularity. For example, each of these declare precedence is perfectly
-legal:
-
-[source, java]
-....
-declare precedence: B, A;
-declare precedence: A, B;
-....
-
-And a system in which both constraints are active may also be legal, so
-long as advice from `A` and `B` don't share a join point. So this is an
-idiom that can be used to enforce that `A` and `B` are strongly independent.
-
-===== Applies to concrete aspects
-
-Consider the following library aspects:
-
-[source, java]
-....
-abstract aspect Logging {
- abstract pointcut logged();
-
- before(): logged() {
- System.err.println("thisJoinPoint: " + thisJoinPoint);
- }
-}
-
-abstract aspect MyProfiling {
- abstract pointcut profiled();
-
- Object around(): profiled() {
- long beforeTime = System.currentTimeMillis();
- try {
- return proceed();
- } finally {
- long afterTime = System.currentTimeMillis();
- addToProfile(thisJoinPointStaticPart, afterTime - beforeTime);
- }
- }
-
- abstract void addToProfile(
- org.aspectj.JoinPoint.StaticPart jp,
- long elapsed
- );
-}
-....
-
-In order to use either aspect, they must be extended with concrete
-aspects, say, MyLogging and MyProfiling. Because advice only applies
-from concrete aspects, the declare precedence form only matters when
-declaring precedence with concrete aspects. So
-
-[source, java]
-....
-declare precedence: Logging, Profiling;
-....
-
-has no effect, but both
-
-[source, java]
-....
-declare precedence: MyLogging, MyProfiling;
-declare precedence: Logging+, Profiling+;
-....
-
-are meaningful.
-
-==== Statically determinable pointcuts
-
-Pointcuts that appear inside of `declare` forms have certain
-restrictions. Like other pointcuts, these pick out join points, but they
-do so in a way that is statically determinable.
-
-Consequently, such pointcuts may not include, directly or indirectly
-(through user-defined pointcut declarations) pointcuts that discriminate
-based on dynamic (runtime) context. Therefore, such pointcuts may not be
-defined in terms of
-
-* `cflow`
-* `cflowbelow`
-* `this`
-* `target`
-* `args`
-* `if`
-
-all of which can discriminate on runtime information.
-
-[[semantics-aspects]]
-=== Aspects
-
-An aspect is a crosscutting type defined by the `aspect` declaration.
-
-==== Aspect Declaration
-
-The `aspect` declaration is similar to the `class` declaration in that
-it defines a type and an implementation for that type. It differs in a
-number of ways:
-
-===== Aspect implementation can cut across other types
-
-In addition to normal Java class declarations such as methods and
-fields, aspect declarations can include AspectJ declarations such as
-advice, pointcuts, and inter-type declarations. Thus, aspects contain
-implementation declarations that can can cut across other types
-(including those defined by other aspect declarations).
-
-===== Aspects are not directly instantiated
-
-Aspects are not directly instantiated with a new expression, with
-cloning, or with serialization. Aspects may have one constructor
-definition, but if so it must be of a constructor taking no arguments
-and throwing no checked exceptions.
-
-===== Nested aspects must be `static`
-
-Aspects may be defined either at the package level, or as a `static`
-nested aspect -- that is, a `static` member of a class, interface, or
-aspect. If it is not at the package level, the aspect _must_ be defined
-with the `static` keyword. Local and anonymous aspects are not allowed.
-
-==== Aspect Extension
-
-To support abstraction and composition of crosscutting concerns, aspects
-can be extended in much the same way that classes can. Aspect extension
-adds some new rules, though.
-
-===== Aspects may extend classes and implement interfaces
-
-An aspect, abstract or concrete, may extend a class and may implement a
-set of interfaces. Extending a class does not provide the ability to
-instantiate the aspect with a new expression: The aspect may still only
-define a null constructor.
-
-===== Classes may not extend aspects
-
-It is an error for a class to extend or implement an aspect.
-
-===== Aspects extending aspects
-
-Aspects may extend other aspects, in which case not only are fields and
-methods inherited but so are pointcuts. However, aspects may only extend
-abstract aspects. It is an error for a concrete aspect to extend another
-concrete aspect.
-
-==== Aspect instantiation
-
-Unlike class expressions, aspects are not instantiated with `new`
-expressions. Rather, aspect instances are automatically created to cut
-across programs. A program can get a reference to an aspect instance
-using the static method `aspectOf(..)`.
-
-Because advice only runs in the context of an aspect instance, aspect
-instantiation indirectly controls when advice runs.
-
-The criteria used to determine how an aspect is instantiated is
-inherited from its parent aspect. If the aspect has no parent aspect,
-then by default the aspect is a singleton aspect. How an aspect is
-instantiated controls the form of the `aspectOf(..)` method defined on
-the concrete aspect class.
-
-===== Singleton Aspects
-
-* `aspect Id { ... }`
-* `aspect Id issingleton() { ... }`
-
-By default (or by using the modifier `issingleton()`) an aspect has
-exactly one instance that cuts across the entire program. That instance
-is available at any time during program execution from the static method
-`aspectOf()` automatically defined on all concrete aspects -- so, in the
-above examples, `A.aspectOf()` will return ``A``'s instance. This aspect
-instance is created as the aspect's classfile is loaded.
-
-Because the an instance of the aspect exists at all join points in the
-running of a program (once its class is loaded), its advice will have a
-chance to run at all such join points.
-
-(In actuality, one instance of the aspect `A` is made for each version of
-the aspect `A`, so there will be one instantiation for each time `A` is
-loaded by a different classloader.)
-
-===== Per-object aspects
-
-* `aspect Id perthis( Pointcut ) { ... }`
-* `aspect Id pertarget( Pointcut ) { ... }`
-
-If an aspect `A` is defined `perthis(Pointcut)`, then one object of type `A`
-is created for every object that is the executing object (i.e., `this`)
-at any of the join points picked out by `Pointcut`. The advice defined
-in `A` will run only at a join point where the currently executing object
-has been associated with an instance of `A`.
-
-Similarly, if an aspect `A` is defined `pertarget(Pointcut)`, then one
-object of type `A` is created for every object that is the target object
-of the join points picked out by `Pointcut`. The advice defined in `A`
-will run only at a join point where the target object has been
-associated with an instance of `A`.
-
-In either case, the static method call `A.aspectOf(Object)` can be used
-to get the aspect instance (of type `A`) registered with the object. Each
-aspect instance is created as early as possible, but not before reaching
-a join point picked out by `Pointcut` where there is no associated
-aspect of type `A`.
-
-Both `perthis` and `pertarget` aspects may be affected by code the
-AspectJ compiler controls, as discussed in the xref:implementation.adoc#implementation[Implementation Notes]
-appendix.
-
-===== Per-control-flow aspects
-
-* `aspect Id percflow( Pointcut ) { ... }`
-* `aspect Id percflowbelow( Pointcut ) { ... }`
-
-If an aspect `A` is defined `percflow(Pointcut)` or
-`percflowbelow(Pointcut)`, then one object of type `A` is created for each
-flow of control of the join points picked out by `Pointcut`, either as
-the flow of control is entered, or below the flow of control,
-respectively. The advice defined in `A` may run at any join point in or
-under that control flow. During each such flow of control, the static
-method `A.aspectOf()` will return an object of type `A`. An instance of
-the aspect is created upon entry into each such control flow.
-
-===== Aspect instantiation and advice
-
-All advice runs in the context of an aspect instance, but it is possible
-to write a piece of advice with a pointcut that picks out a join point
-that must occur before asopect instantiation. For example:
-
-[source, java]
-....
-public class Client
-{
- public static void main(String[] args) {
- Client c = new Client();
- }
-}
-
-aspect Watchcall {
- pointcut myConstructor(): execution(new(..));
-
- before(): myConstructor() {
- System.err.println("Entering Constructor");
- }
-}
-....
-
-The before advice should run before the execution of all constructors in
-the system. It must run in the context of an instance of the Watchcall
-aspect. The only way to get such an instance is to have Watchcall's
-default constructor execute. But before that executes, we need to run
-the before advice...
-
-There is no general way to detect these kinds of circularities at
-compile time. If advice runs before its aspect is instantiated, AspectJ
-will throw a
-xref:../api/org/aspectj/lang/NoAspectBoundException.html[`org.aspectj.lang.NoAspectBoundException`].
-
-==== Aspect privilege
-
-* `privileged aspect Id { ... }`
-
-Code written in aspects is subject to the same access control rules as
-Java code when referring to members of classes or aspects. So, for
-example, code written in an aspect may not refer to members with default
-(package-protected) visibility unless the aspect is defined in the same
-package.
-
-While these restrictions are suitable for many aspects, there may be
-some aspects in which advice or inter-type members needs to access
-private or protected resources of other types. To allow this, aspects
-may be declared `privileged`. Code in priviliged aspects has access to
-all members, even private ones.
-
-[source, java]
-....
-class C {
- private int i = 0;
- void incI(int x) { i = i+x; }
-}
-
-privileged aspect A {
- static final int MAX = 1000;
-
- before(int x, C c): call(void C.incI(int)) && target(c) && args(x) {
- if (c.i+x > MAX) throw new RuntimeException();
- }
-}
-....
-
-In this case, if `A` had not been declared `privileged`, the field reference
-`c.i` would have resulted in an error signaled by the compiler.
-
-If a privileged aspect can access multiple versions of a particular
-member, then those that it could see if it were not privileged take
-precedence. For example, in the code
-
-[source, java]
-....
-class C {
- private int i = 0;
- void foo() { }
-}
-
-privileged aspect A {
- private int C.i = 999;
-
- before(C c): call(void C.foo()) target(c) {
- System.out.println(c.i);
- }
-}
-....
-
-``A``'s private inter-type field `C.i`, initially bound to 999, will be
-referenced in the body of the advice in preference to ``C``'s privately
-declared field, since `A` would have access to its own inter-type
-fields even if it were not privileged.
-
-Note that a privileged aspect can access private inter-type declarations
-made by other aspects, since they are simply considered private members
-of that other aspect.