Call, execution, get, and set join points may potentially have multiple signatures. All other join points have exactly one signature. The following table summarizes the constituent parts of a join point signature for the different kinds of join point.
Join Point Kind | Return Type | Declaring Type | Id | Parameter Types | Field Type | Exception Type |
---|---|---|---|---|---|---|
Method call | + | + | + | + | ||
Method execution | + | + | + | + | ||
Constructor call | + | + | ||||
Constructor execution | + | + | ||||
Field get | + | + | + | |||
Field set | + | + | + | |||
Pre-initialization | + | + | ||||
Initialization | + | + | ||||
Static initialization | + | |||||
Handler | + | |||||
Advice execution | + | + |
Note that whilst an advice excetution join point has a signature comprising the declaring type of the advice and the advice parameter types, the adviceexecution pointcut designator does not support matching based on this signature.
The signatures for most of the join point kinds should be self-explanatory, except for field get and set, and method call and execution join points, which can have multiple signatures. Each signature of a method call or execution join point has the same id and parameter types, but the declaring type and return type (with covariance) may vary. Each signature of a field get or set join point has the same id and field type, but the declaring type may vary.
The following sections examine signatures for these join points in more detail.
For a call join point where a call is made to a method m(parameter_types) on a target type T (where T is the static type of the target):
T t = new T(); t.m("hello"); <= call join point occurs when this line is executed
Then the signature R(T) T.m(parameter_types) is a signature of the call join point, where R(T) is the return type of id in T, and parameter_types are the parameter types of m. If T itself does not declare a definition of m(parameter_types), then R(T) is the return type in the definition of m that T inherits. Given the call above, and the definition of T.m:
interface Q { R m(String s); } class P implements Q { R m(String s) {...} } class S extends P { R' m(String s) {...} } class T extends S {}
Then R' T.m(String) is a signature of the call join point for t.m("hello").
For each ancestor (super-type) A of T, if m(parameter_types) is defined for that super-type, then R(A) A.m(parameter_types) is a signature of the call join point, where R(A) is the return type of m(parameter_types) as defined in A, or as inherited by A if A itself does not provide a definition of m(parameter_types).
Continuing the example from above,we can deduce that
R' S.m(String) R P.m(String) R Q.m(String)
are all additional signatures for the call join point arising from the call t.m("hello"). Thus this call join point has four signatures in total. Every signature has the same id and parameter types, and a different declaring type.
Join point signatures for execution join points are defined in a similar manner to signatures for call join points. Given the hierarchy:
interface Q { R m(String s); } class P implements Q { R m(String s) {...} } class S extends P { R' m(String s) {...} } class T extends S { } class U extends T { R' m(String s) {...} }
Then the execution join point signatures arising as a result of the call to u.m("hello") are:
R' U.m(String) R' S.m(String) R P.m(String) R Q.m(String)
Each signature has the same id and parameter types, and a different declaring type. There is one signature for each type that provides its own declaration of the method. Hence in this example there is no signature R' T.m(String) as T does not provide its own declaration of the method.
For a field get join point where an access is made to a field f of type F on a object with declared type T, then F T.f is a signature of the get join point.
If T does not directly declare a member f, then for each super type S of T, up to and including the most specific super type of T that does declare the member f, F S.f is a signature of the join point. For example, given the hierarchy:
class P { F f; } class S extends P { F f; } class T extends S { }
Then the join point signatures for a field get join point of the field f on an object with declared type T are:
F S.f F T.f
The signatures for a field set join point are derived in an identical manner.