Chapter 3. Joinpoint and Pointcut Expressions

The pointcut language is a tool that allows joinpoint matching. A pointcut expression determines in which joinpoint executions of the base system an advice should be invoked.

In this Chapter, we will explore the syntax of pointcut expressions.

We will also see the API used to represent a matched joinpoint during advice execution, and how this relates to pointcut expression constructs.

3.1. Wildcards

There are two types of wildcards you can use within pointcut expressions

  • * Is a regular wildcard that matches zero or more characters. It can be used within any type expression, field, or method name, but not in an annotation expression
  • .. Is used to specify any number of parameters in an constructor or method expression. .. following a package-name is used to specify all classes from within a given package ut not within sub-packages. e.g org.acme.. matches org.acme.Foo and org.acme.Bar, but it does not match org.acme.sub.SubFoo.

3.2. Type Patterns

Type patterns are defined by an annotation or by fully qualified class name. Annotation expressions are not allowed to have wildcards within them, but class expressions are.

  • org.acme.SomeClass matches that class.
  • org.acme.* will match org.acme.SomeClass as well as org.acme.SomeClass.SomeInnerClass
  • @javax.ejb.Entity will match any class tagged as such.
  • String or Object are illegal. You must specify the fully qualified name of every java class. Even those under the java.lang package.

To reference all subtypes of a certain class (or implementors of an interface), the $instanceof{} expression can be used. Wildcards and annotations may also be used within $instanceof{} expressions.

         $instanceof{org.acme.SomeInterface}
         $instanceof{@org.acme.SomeAnnotation}
         $instanceof{org.acme.interfaces.*}
      

are all allowed.

For very complex type expressions, the Typedef construct can be used. To reference a Typedef within a class expression $typedef{id} is used.

3.3. Method Patterns

public void org.acme.SomeClass->methodName(java.lang.String)

The attributes( public, static, private) of the method are optional. If the attribute is left out then any attribute is assumed. Attributes accept the ! modifier for negation.

public !static void org.acme.SomeClass->*(..)

$instanceof{} can be used in place of the class name.

void $instanceof{org.acme.SomeInterface}->methodName(java.lang.String)

To pick out all toString() methods of all classes within the org.acme package, we can use org.acme.. in place of the class name.

java.lang.String org.acme..->toString()

To only match methods from a given interface you can use the $implements{} or $implementing{} keywords in place of the method name. $implements{} only matches methods from the exact interface(s) given, while $implementing{} matches methods from the interface(s) given AND their super interfaces.

void $instanceof{org.acme.IfA}->$implements(org.acme.IfA)(..)
void $instanceof{org.acme.IfB}->$implementing(org.acme.IfA, org.acme.IfB)(..)

Annotations can be used in place of the class name. The below example matches any methodName() of a tagged @javax.ejb.Entity class.

void @javax.ejb.Entity->methodName(java.lang.String)

Annotations can be also be used in place of the method name. The below examples matches any method tagged as @javax.ejb.Tx.

* *->@javax.ejb.Tx(..)

In addition you can use typedefs, $instanceof{}, annotations and wildcards for method parameters and return types. The following matches all methods called loadEntity that return a class annotated with @javax.ejb.Entity, that takes a class (or a class whose superclass/interface is) annotated as @org.acme.Ann and any class that matches java.*.String (such as java.lang.String).

@javax.ejb.Entity *->loadEntity($instanceof{@org.acme.Ann}, java.*.String)
You can also include an optional throws clause in the pointcut expression:
public void org.acme.SomeClass->methodName(java.lang.String) \
      throws org.acme.SomeException, java.lang.Exception
If any exceptions are present in the pointcut expression they must be present in the throws clause of the methods to be matched.

3.4. Constructor Patterns

public org.acme.SomeClass->new(java.lang.String)

Constructor expressions are made up of the fully qualified classname and the new keyword The attributes( public, static, private) of the method are optional. If the attribute is left out then any attribute is assumed. Attributes accept the ! modifier for negation.

!public org.acme.SomeClass->new(..)

$instanceof{} can be used in the class name.

$instanceof{org.acme.SomeInterface}->new(..)

To pick out all no-args constructors of all classes within the org.acme package, we can use org.acme.. in place of the class name.

org.acme..->new()

Annotations can be used in place of the class name. The below example matches any constructor of a tagged @javax.ejb.Entity class.

@javax.ejb.Entity->new(..)

Annotations can be also be used in place of the new keyword. The below examples matches any constructor tagged as @javax.ejb.MethodPermission.

*->@javax.ejb.MethodPermission(..)

In addition, just as for methods you can use typedefs, $instanceof{}, annotations and wildcards for constructor parameters. The following matches all constructors that take a class annotated as @org.acme.Ann and any class that matches java.*.String (such as java.lang.String).

*->new(@org.acme.Ann, java.*.String)

You can also include an optional throws clause in the pointcut expression:

public void org.acme.SomeClass->new(java.lang.String) \
      throws org.acme.SomeException, java.lang.Exception

If any exceptions are present in the pointcut expression they must be present in the throws clause of the constructors to be matched.

3.5. Field Patterns

public java.lang.String org.acme.SomeClass->fieldname

Constructor expressions are made up of the type, the fully qualified classname where the field resides and the field's name. The attributes( public, static, private) of the field are optional. If the attribute is left out then any attribute is assumed. Attributes accept the ! modifier for negation.

!public java.lang.String org.acme.SomeClass->*

$instanceof{} can be used in the class name. The below expression matches any field of any type or subtype of org.acme.SomeInterface

* $instanceof{org.acme.SomeInterface}->*

Annotations can be used in place of the class name. The below example matches any field where the type class is tagged with @javax.ejb.Entity.

* @javax.ejb.Entity->*

Annotations can be also be used in place of the field name. The below examples matches any field tagged as @org.jboss.Injected.

* *->@org.jboss.Injected

In addition, you can use typedefs, $instanceof{}, annotations and wildcards for field types. The following matches all fields where the type class has been tagged with @javax.ejb.Entity.

@javax.ejb.Entity *->*

To pick out all fields annotated with @org.foo.Transient within the org.acme package, we can use org.acme.. in place of the class name, and @org.foo.Transient in please of the field name

* org.acme..->@org.foo.Transient

3.6. Pointcuts

Pointcuts use class, field, constructor, and method expressions to specify the actual joinpoint that should be intercepted/watched.

execution(method or constructor)
execution(public void Foo->method()
execution(public Foo->new())

execution is used to specify that you want an interception to happen whenever a method or constructor is called. The the first example of matches anytime a method is called, the second matches a constructor. System classes cannot be used within execution expressions because it is impossible to instrument them.

construction(constructor)
construction(public Foo->new())

construction is used to specify that you want aspects to run within the constructor. The execution pointcut requires that any code that calls new() must be instrumented by the compiler. With construction the aspects are weaved right within the constructor after all the code in the constructor. The aspects are appended to the code of the constructor.

get (field expression)
get(public int Foo->fieldname)

get is used to specify that you want an interception to happen when a specific field is accessed for a read.

set(field expression)
get(public int Foo->fieldname)

set is used to specify that you want an interception to happen when a specific field is accessed for a write.

field(field expression)
field(public int Foo->fieldname)

field is used to specify that you want an interception to happen when a specific field is accessed for a read or a write.

all(type expression)
all(org.acme.SomeClass)
all(@org.jboss.security.Permission)

all is used to specify any constructor, method or field of a particular class will be intercepted. If an annotation is used, it matches the member's annotation, not the class's annotation.

call(method or constructor)
call(public void Foo->method()
call(public Foo->new())

call is used to specify any constructor or method that you want intercepted. It is different than execution in that the interception happens at the caller side of things and the caller information is available within the Invocation object. call can be used to intercept System classes because the bytecode weaving happens within the callers bytecode.

within(type expression)
within(org.acme.SomeClass)
within(@org.jboss.security.Permission)

within matches any joinpoint (method or constructor call) within any code within a particular type.

withincode(method or constructor)
withincode(public void Foo->method()
withincode(public Foo->new())

withincode matches any joinpoint (method or constructor call) within a particular method or constructor.

has(method or constructor)
has(void *->@org.jboss.security.Permission(..))
has(*->new(java.lang.String))

has is an additional requirement for matching. If a joinpoint is matched, its class must also have a constructor or method that matches the has expression.

hasfield(field expression)
hasfield(* *->@org.jboss.security.Permission)
hasfield(public java.lang.String *->*)

has is an additional requirement for matching. If a joinpoint is matched, its class must also have a field that matches the hasfield expression.

3.7. Pointcut Composition

Pointcuts can be composed into boolean expressions.

  • ! logical not.
  • AND logical and.
  • OR logical or.
  • Paranthesis can be used for grouping expressions.

Here's some examples.

call(void Foo->someMethod()) AND withincode(void Bar->caller())
execution(* *->@SomeAnnotation(..)) OR field(* *->@SomeAnnotation)

3.8. Pointcut References

Pointcuts can be named in XML (Chapter 5, XML Bindings) or annotation (Chapter 6, Annotation Bindings) bindings. They can be referenced directly within a pointcut expression.

some.named.pointcut OR call(void Foo->someMethod())

3.9. Typedef Expressions

Sometimes, when writing pointcuts, you want to specify a really complex type they may or may not have boolean logic associated with it. You can group these complex type definitions into a JBoss AOP Typedef either in XML or as an annotation (See later in this document). Typedef expressions can also be used within introduction expressions. Typedef expressions can be made up of has, hasfield, and class expressions. class takes a fully qualified class name, or an $instanceof{} expression.

class(org.pkg.*) OR has(* *->@Tx(..)) AND !class($instanceof{org.foo.Bar})

3.10. Joinpoints

After getting acquainted with all pointcut constructs, let's see how this reflects on the API available to advices during their execution.

3.10.1. Joinpoint Beans

JBoss AOP provides JoinPoint Beans, so that an advice can access all information regarding a joinpoint during its execution. This information consists of context values, explained in the next subsection, and of reflection objects (java.lang.reflection). The reflection objects describe the joinpoint being intercepted like a java.lang.Method for a method execution joinpoint).

There are two groups of beans. The first one is the Invocation beans group. All classes of this group are subclasses of org.jboss.aop.joinpoint.Invocation. The Invocation class was presented in Chapter 2 as a runtime encapsulation of a joinpoint. An Invocation object also contains an interceptor chain, where all advices and interceptors that intercept the joinpoint are stored. Invocation beans provide the invokeNext() method, responsible for proceeding execution to the next advice in the interceptor chain (if there is an advice that has not started execution yet) or to the joinpoint itself (if all advices contained in the interceptor chain have already started running). We will see more on this in the next chapter.

The other group of beans contains only information regarding the joinpoint itself, and are called the JoinPointBean group. All beans of this group are defined in interfaces, with org.jboss.joinpoint.JoinPointBean being their common superinterface.

The Invocation objects are available only to around advices. All other types of advices can use the JoinPointBean types to access joinpoint specific data.

In both groups there is a specific type for each joinpoint type. The type of bean corresponding to each joinpoint type can be seen in Table 3.1, “ Joinpoint Types Table ”. All beans are in the package org.jboss.aop.joinpoint.

3.10.2. Context Values

According to the type of the joinpoint, there are specific context values available.

The context values are:

  • return value: joinpoints like a constructor execution or a non-void method call, have a return value.
  • arguments: the arguments of a constructor or method execution joinpoint are the arguments received by the constructor or method. Similarly, the arguments of a call are the arguments received by the method or constructor being called.
  • target: the target object of a joinpoint varies according to the joinpoint type. For method executions and calls, it refers to the object whose method is being executed (available only on non-static methods). For field reads and writes, it refers to the object that contains that field.
  • caller: the caller object is available only on call joinpoints, and it refers to the object whose method or constructor is performing the call (notice the caller object is not available if the call is inside a static method).

Table 3.1, “ Joinpoint Types Table ” shows what context values may be available depending on the joinpoint type.

Table 3.1.  Joinpoint Types Table

JoinpointPointcut ConstructBeanContextValues
InvocationJoinpointBeanTargetCallerArgumentsReturn Value
field readread, field, allFieldReadInvocationFieldAccessYesNoNoYes
field writewrite, field, allFieldWriteInvocationFieldAccessYesNoYesNo
method executionexecution, allMethodInvocationMethodExecutionYesNoYesYes
constructor executionexecutionConstructorInvocationConstructorExecutionNoNoYesYes
constructionconstructionConstructionInvocationConstructorExecutionYesNoYesNo
method callcall, within, withincodeCallerInvocation, MethodCalledByConstructorInvocation, MethodCalledByMethodInvocationMethodCall, MethodCallByConstructor, MethodCallByMethodYesYesYesYes
constructor callcall, within, withincodeCallerInvocation, ConstructorCalledByConstructorInvocation, ConstructorCalledByMethodInvocationConstructorCall, ConstructorCallByConstructor, ConstructorCallByMethodYesYesYesYes
The first column shows the joinpoint type. The second column shows which pointcut constructs can identify a joinpoint of that type. has and hasfield are additional constructs, and therefore are not shown in this table. The third column shows the specific type of joinpoint bean class that is used to represent that joinpoint. This column is split into two: one for the Invocation beans, the other one for the JoinPointBean ones. The fourth column is composed of four subcolumns, and it shows the context values avaialble for each joinpoint type. Notice that, on some of these values, there are additional restrictions for their availability. Like, for example, there is no target on a static method execution.