Pointcuts and Advices
Pointcut and advice declarations can be made using the @Pointcut, @Before, @After, @AfterThrowing, and @Around annotations.
Advice
In this section we first discuss the use of annotations for simple advice declarations. Then we show how JoinPoint and its siblings are handled in the body of advice and discuss the treatment of proceed in around advice.
Using the annotation style, an advice declaration is written as a regular PHP method with one of the @Before, @After, @AfterThrowing, or @Around annotations. Except in the case of around advice, the method should return void. The method should be declared public.
The following example shows a simple before advice
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
@After advice declarations take exactly the same form as @Before, as do the forms of @AfterReturning and @AfterThrowing that do not expose the return type or thrown exception respectively.
For around advice, we can do anything with original invocation, for example:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Pointcuts
Pointcuts are specified using the Go\Lang\Annotation\Pointcut annotation on a method declaration.
As a general rule, the @Pointcut annotated method must have an empty method body. Here is a simple example of a pointcut declaration:
1 2 3 4 5 6 7 8 |
|
Declared pointcut can be referenced in advice by short name pointcut="examplePublicMethods()"
or by full-qualified name, for example pointcut="Aspect\DebugAspect->examplePublicMethods()"
.
For pointcut syntax, please see Pointcut Reference page.
Annotation pointcut
Annotation pointcut can be used to match against the set of annotations on the annotated element. An annotation pattern element has following form: @annotation(Annotation\Class\Name)
. This pointcut will match all methods with Anotation\Class\Name
annotation in phpDoc block. Following example shows how to implement transparent caching with aspects and annotation pointcut:
First of all, create an annotation class:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Next step is to add this annotation to method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
And then just create an around advice with annotation pointcut:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
Advice ordering
Each advice can have custom order that will be used during joinpoint invocation. To define the order just fill it in annotation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Advice with smallest order will be executed first. If several advices uses the same value for order then they will be executed in the order of registration in the container.
Introductions
Introductions (known also as inter-type declarations) enable an aspect to declare additional interfaces for advised objects, and to provide an implementation of that interface with the help of traits.
An introduction is made using the @DeclareParents annotation for the property inside aspect class. This annotation is used to declare that matching types have a new parent (hence the name). For example, given an interface Serializable, and an implementation of that interface SerializableImpl, the following aspect declares that Example class is also implements the Serializable interface:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Here, value
is a name of the classes to apply advice (can contain ‘*’ as wildcard), interface
declares additional interface for classes and defaultImpl
should specify a trait with realization. For Serializable interface it can looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|